<commit_before>"""
The Ziptie class.
"""

from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt

import becca.tools as tools
import becca.ziptie_numba as nb


class Ziptie(object):
    """
    An incremental unsupervised clustering algorithm.

    Input channels are clustered together into mutually co-active sets.
    A helpful metaphor is bundling cables together with zip ties.
    Cables that carry related signals are commonly co-active,
    and are grouped together. Cables that are co-active with existing
    bundles can be added to those bundles. A single cable may be ziptied
    into several different bundles. Co-activity is estimated
    incrementally, that is, the algorithm updates the estimate after
    each new set of signals is received.

    Zipties are arranged hierarchically within the agent's drivetrain.
    The agent begins with only one ziptie and creates subsequent
    zipties as previous ones mature.

    When stacked with other levels,
    zipties form a sparse deep neural network (DNN).
    This DNN has the extremely desirable characteristic of
    l-0 sparsity--the number of non-zero weights are minimized.
    The vast majority of weights in this network are zero,
    and the rest are one.
    This makes sparse computation feasible and allows for
    straightforward interpretation and visualization of the
    features at each level.
    """


    def __init__(self,
                 num_cables,
                 num_bundles=None,
                 level=0,
                 name=None,
                 debug=False):
        """
        Initialize each level, pre-allocating data structures.

        Parameters
        ----------
        debug : boolean
            Indicate whether to print informative status messages
            during execution.
        level : int
            The position of this Ziptie in the hierarchy.
        num_bundles : int
            The number of bundle outputs from the Ziptie.
        num_cables : int
            The number of inputs to the Ziptie.
        name : str
            The name assigned to the Ziptie.
            Default is 'anonymous'.
        """
        # level : int
        #     The position of this Ziptie in the hierarchy.
        self.level = level
        # name : str
        #     The name associated with the Ziptie.
        if name is None:
            self.name = '_'.join(['ziptie', str(self.level)])
        else:
            self.name = name
        # debug : boolean
        #     Indicate whether to print informative status messages
        #     during execution.
        self.debug = debug
        # max_num_cables : int
        #     The maximum number of cable inputs allowed.
        self.max_num_cables = num_cables
        # max_num_bundles : int
        #     The maximum number of bundle outputs allowed.
        if num_bundles is None:
            self.max_num_bundles = self.max_num_cables
        else:
            self.max_num_bundles = num_bundles
        # num_bundles : int
        #     The number of bundles that have been created so far.
        self.num_bundles = 0
        # nucleation_threshold : float
        #     Threshold above which nucleation energy results in nucleation.
        #     With each level, increase this by a factor of 5. This gives
        #     Each level a chance to mature before the one above it.
        self.nucleation_threshold = 50. * 5. ** self.level
        # agglomeration_threshold
        #     Threshold above which agglomeration energy results
        #     in agglomeration.
        #self.agglomeration_threshold = .5 * self.nucleation_threshold
        self.agglomeration_threshold = 1. * self.nucleation_threshold
        # activity_threshold : float
        #     Threshold below which input activity is teated as zero.
        #     By ignoring the small activity values,
        #     computation gets much faster.
        self.activity_threshold = .1
        # bundles_full : bool
        #     If True, all the bundles in the Ziptie are full
        #     and learning stops. This is another way to speed up
        #     computation.
        self.bundles_full = False
        # cable_activities : array of floats
        #     The current set of input actvities.
        self.cable_activities = np.zeros(self.max_num_cables)
        # bundle_activities : array of floats
        #     The current set of bundle activities.
        self.bundle_activities = np.zeros(self.max_num_bundles)
        # nonbundle_activities : array of floats
        #     The set of input activities that do not contribute
        #     to any of the current bundle activities.
        self.nonbundle_activities = np.zeros(self.max_num_cables)

        # bundle_map_size : int
        #     The maximum number of non-zero entries in the bundle map.
        self.bundle_map_size = 8
        # bundle_map_cols, bundle_map_rows : array of ints
        #     To represent the sparse 2D bundle map, a pair of row and col
        #     arrays are used. Rows are bundle indices, and cols are
        #     feature indices.  The bundle map shows which cables
        #     are zipped together to form which bundles.
        self.bundle_map_rows = -np.ones(self.bundle_map_size).astype(int)
        self.bundle_map_cols = -np.ones(self.bundle_map_size).astype(int)
        # n_map_entries: int
        #     The total number of bundle map entries that
        #     have been created so far.
        self.n_map_entries = 0
        # agglomeration_energy : 2D array of floats
        #     The accumulated agglomeration energy for each bundle-cable pair.
        self.agglomeration_energy = np.zeros((self.max_num_bundles,
                                              self.max_num_cables))
        # nucleation_energy : 2D array of floats
        #     The accumualted nucleation energy associated
        #     with each cable-cable pair.
        self.nucleation_energy = np.zeros((self.max_num_cables,
                                           self.max_num_cables))


    def featurize(self, new_cable_activities, bundle_weights=None):
        """
        Calculate how much the cables' activities contribute to each bundle.

        Find bundle activities by taking the minimum input value
        in the set of cables in the bundle. The bulk of the computation
        occurs in ziptie_numba.find_bundle_activities.
        """
        self.cable_activities = new_cable_activities.copy()
        #self.nonbundle_activities = self.cable_activities.copy()
        #self.bundle_activities = np.zeros(self.max_num_bundles)
        self.bundle_activities = 1e3 * np.ones(self.max_num_bundles)
        if bundle_weights is None:
            bundle_weights = np.ones(self.max_num_bundles)
        if self.n_map_entries > 0:
            #nb.find_bundle_activities(
            #    self.bundle_map_rows[:self.n_map_entries],
            #    self.bundle_map_cols[:self.n_map_entries],
            #    self.nonbundle_activities,
            #    self.bundle_activities,
            #    bundle_weights, self.activity_threshold)
            for i_map_entry in xrange(self.n_map_entries):
                i_bundle = self.bundle_map_rows[i_map_entry]
                i_cable = self.bundle_map_cols[i_map_entry]<commit_msg>changed xrange to range, 3.5 doesn't have an xrange<commit_after>"""
The Ziptie class.
"""

from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt

import becca.tools as tools
import becca.ziptie_numba as nb


class Ziptie(object):
    """
    An incremental unsupervised clustering algorithm.

    Input channels are clustered together into mutually co-active sets.
    A helpful metaphor is bundling cables together with zip ties.
    Cables that carry related signals are commonly co-active,
    and are grouped together. Cables that are co-active with existing
    bundles can be added to those bundles. A single cable may be ziptied
    into several different bundles. Co-activity is estimated
    incrementally, that is, the algorithm updates the estimate after
    each new set of signals is received.

    Zipties are arranged hierarchically within the agent's drivetrain.
    The agent begins with only one ziptie and creates subsequent
    zipties as previous ones mature.

    When stacked with other levels,
    zipties form a sparse deep neural network (DNN).
    This DNN has the extremely desirable characteristic of
    l-0 sparsity--the number of non-zero weights are minimized.
    The vast majority of weights in this network are zero,
    and the rest are one.
    This makes sparse computation feasible and allows for
    straightforward interpretation and visualization of the
    features at each level.
    """


    def __init__(self,
                 num_cables,
                 num_bundles=None,
                 level=0,
                 name=None,
                 debug=False):
        """
        Initialize each level, pre-allocating data structures.

        Parameters
        ----------
        debug : boolean
            Indicate whether to print informative status messages
            during execution.
        level : int
            The position of this Ziptie in the hierarchy.
        num_bundles : int
            The number of bundle outputs from the Ziptie.
        num_cables : int
            The number of inputs to the Ziptie.
        name : str
            The name assigned to the Ziptie.
            Default is 'anonymous'.
        """
        # level : int
        #     The position of this Ziptie in the hierarchy.
        self.level = level
        # name : str
        #     The name associated with the Ziptie.
        if name is None:
            self.name = '_'.join(['ziptie', str(self.level)])
        else:
            self.name = name
        # debug : boolean
        #     Indicate whether to print informative status messages
        #     during execution.
        self.debug = debug
        # max_num_cables : int
        #     The maximum number of cable inputs allowed.
        self.max_num_cables = num_cables
        # max_num_bundles : int
        #     The maximum number of bundle outputs allowed.
        if num_bundles is None:
            self.max_num_bundles = self.max_num_cables
        else:
            self.max_num_bundles = num_bundles
        # num_bundles : int
        #     The number of bundles that have been created so far.
        self.num_bundles = 0
        # nucleation_threshold : float
        #     Threshold above which nucleation energy results in nucleation.
        #     With each level, increase this by a factor of 5. This gives
        #     Each level a chance to mature before the one above it.
        self.nucleation_threshold = 50. * 5. ** self.level
        # agglomeration_threshold
        #     Threshold above which agglomeration energy results
        #     in agglomeration.
        #self.agglomeration_threshold = .5 * self.nucleation_threshold
        self.agglomeration_threshold = 1. * self.nucleation_threshold
        # activity_threshold : float
        #     Threshold below which input activity is teated as zero.
        #     By ignoring the small activity values,
        #     computation gets much faster.
        self.activity_threshold = .1
        # bundles_full : bool
        #     If True, all the bundles in the Ziptie are full
        #     and learning stops. This is another way to speed up
        #     computation.
        self.bundles_full = False
        # cable_activities : array of floats
        #     The current set of input actvities.
        self.cable_activities = np.zeros(self.max_num_cables)
        # bundle_activities : array of floats
        #     The current set of bundle activities.
        self.bundle_activities = np.zeros(self.max_num_bundles)
        # nonbundle_activities : array of floats
        #     The set of input activities that do not contribute
        #     to any of the current bundle activities.
        self.nonbundle_activities = np.zeros(self.max_num_cables)

        # bundle_map_size : int
        #     The maximum number of non-zero entries in the bundle map.
        self.bundle_map_size = 8
        # bundle_map_cols, bundle_map_rows : array of ints
        #     To represent the sparse 2D bundle map, a pair of row and col
        #     arrays are used. Rows are bundle indices, and cols are
        #     feature indices.  The bundle map shows which cables
        #     are zipped together to form which bundles.
        self.bundle_map_rows = -np.ones(self.bundle_map_size).astype(int)
        self.bundle_map_cols = -np.ones(self.bundle_map_size).astype(int)
        # n_map_entries: int
        #     The total number of bundle map entries that
        #     have been created so far.
        self.n_map_entries = 0
        # agglomeration_energy : 2D array of floats
        #     The accumulated agglomeration energy for each bundle-cable pair.
        self.agglomeration_energy = np.zeros((self.max_num_bundles,
                                              self.max_num_cables))
        # nucleation_energy : 2D array of floats
        #     The accumualted nucleation energy associated
        #     with each cable-cable pair.
        self.nucleation_energy = np.zeros((self.max_num_cables,
                                           self.max_num_cables))


    def featurize(self, new_cable_activities, bundle_weights=None):
        """
        Calculate how much the cables' activities contribute to each bundle.

        Find bundle activities by taking the minimum input value
        in the set of cables in the bundle. The bulk of the computation
        occurs in ziptie_numba.find_bundle_activities.
        """
        self.cable_activities = new_cable_activities.copy()
        #self.nonbundle_activities = self.cable_activities.copy()
        #self.bundle_activities = np.zeros(self.max_num_bundles)
        self.bundle_activities = 1e3 * np.ones(self.max_num_bundles)
        if bundle_weights is None:
            bundle_weights = np.ones(self.max_num_bundles)
        if self.n_map_entries > 0:
            #nb.find_bundle_activities(
            #    self.bundle_map_rows[:self.n_map_entries],
            #    self.bundle_map_cols[:self.n_map_entries],
            #    self.nonbundle_activities,
            #    self.bundle_activities,
            #    bundle_weights, self.activity_threshold)
            for i_map_entry in range(self.n_map_entries):
                i_bundle = self.bundle_map_rows[i_map_entry]
                i_cable = self.bundle_map_cols[i_map_entry]
{'fraction_non_alphanumeric': 0.05568841817560642, 'fraction_numerical': 0.0025965152032798085, 'mean_word_length': 2.0644891122278057, 'pattern_counts': {'":': 0, '<': 3, '<?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': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4068691', 'n_tokens_mistral': 3995, 'n_tokens_neox': 3834, 'n_words': 1345}