class_docstr: Parameters
  ----------
  
  nbits: int
      Number of bits per weight. Required for ``kmeans`` or ``uniform`` mode, but must
      not be set for ``unique`` or ``custom`` mode. A LUT would have
      2\ :sup:`nbits` entries, where `nbits` can be ``{1, 2, 4, 6, 8}``.
  
  mode: str
      Determine how the LUT is constructed by specifying one of the following:
  
      * ``"kmeans"`` (default): The LUT is generated by `k-means clustering`, a method of vector
        quantization that groups similar data points together to discover underlying
        patterns by using a fixed number (`k`) of clusters in a dataset. A cluster
        refers to a collection of data points aggregated together because of certain
        similarities. `nbits` is required.
  
      * ``"uniform"``: The LUT is generated by a linear histogram.
  
         - ``[v_min, v_min + scale, v_min + 2 * scale, ..., v_max]``
         - Where the weight is in the range ``[v_min, v_max]``, and
           ``scale = (v_max - v_min) / (1 << nbits - 1)``.
         - ``nbits`` is required.
  
         A `histogram` is a representation of the distribution of a continuous variable,
         in which the entire range of values is divided into a series of intervals (or
         `bins`) and the representation displays how many values fall into each bin.
         Linear histograms have one bin at even intervals, such as one bin per integer.
  
      * ``"unique"``: The LUT is generated by unique values in the weights. The weights
        are assumed to be on a discrete lattice but stored in a float data type. This
        parameter identifies the weights and converts them into the palettized representation.
  
        Do not provide ``nbits`` for this mode. ``nbits`` is picked up automatically,
        with the smallest possible value in ``{1, 2, 4, 6, 8}`` such that the
        number of the unique values is ``<= (1 << nbits)``. If the weight has ``> 256``
        unique values, the compression is skipped.
  
        For example:
  
        * If the weights are ``{0.1, 0.2, 0.3, 0.4}`` and ``nbits=2``, the weights are
          converted to ``{00b, 01b, 10b, 11b}``, and the generated LUT is
          ``[0.1, 0.2, 0.3, 0.4]``.
        * If the weights are ``{0.1, 0.2, 0.3, 0.4}`` and ``nbits=1``, nothing happens
          because the weights are not a 1-bit lattice.
        * If the weights are ``{0.1, 0.2, 0.3, 0.4, 0.5}`` and ``nbits=2``, nothing
          happens because the weights are not a 2-bit lattice.
  
      * ``"custom"``: The LUT and palettization parameters are calculated using a custom
        function. If this mode is selected then ``lut_function`` must be provided.
  
        Do not provide ``nbits`` for this mode. The user should customize ``nbits`` in the
        ``lut_function`` implementation.
  
  lut_function: callable
      A callable function which computes the weight palettization parameters. This must
      be provided if the mode is set to ``"custom"``.
  
      weight: np.ndarray
          A float precision numpy array.
  
      Returns: lut: list[float]
          The lookup table.
  
      indices: list[int]
          A list of indices for each element.
  
      The following is an example that extract the ``top_k`` elements as the LUT. Given
      that ``weight = [0.1, 0.5, 0.3, 0.3, 0.5, 0.6, 0.7]``, the ``lut_function``
      produces ``lut = [0, 0.5, 0.6, 0.7], indices = [0, 1, 0, 0, 2, 3]``.
  
      .. sourcecode:: python
  
         def lut_function(weight):
             # In this example, we assume elements in the weights >= 0
             weight = weight.flatten()
             nbits = 4
  
             # Get the LUT, from extracting top k maximum unique elements in the weight to be the LUT
             # Note that k = 1 << nbits - 1, so we have the first element be 0
             unique_elements = np.unique(weight)
             k = (1 << nbits) - 1
             top_k = np.partition(weight, -k)[-k:]
             np.sort(top_k)
             lut = [0.0] + top_k.tolist()
  
             # Compute the indices
             mapping = {v: idx for idx, v in enumerate(lut)}
             indices = [mapping[v] if v in mapping else 0 for v in weight]
  
             return lut, indices
  
  weight_threshold: int
      The size threshold, above which weights are pruned.
      That is, a weight tensor is pruned only if its total number of elements are greater than ``weight_threshold``.
  
      For example, if ``weight_threshold = 1024`` and a weight tensor is of shape ``[10, 20, 1, 1]``, hence ``200``
      elements, it will not be pruned.
  
      * If not provided, it will be set to ``2048``, in which weights bigger than ``2048`` elements are compressed.
class_docstr_tok: ["Parameters","--","--","--","--","--","nbits",":","int","Number","of","bits","per","weight",".","Required","for","``","kmeans","``","or","``","uniform","``","mode",",","but","must","not","be","set","for","``","unique","``","or","``","custom","``","mode",".","A","LUT","would","have","2\\",":","sup",":","`","nbits","`","entries",",","where","`","nbits","`","can","be","``","{","1",",","2",",","4",",","6",",","8","}","``",".","mode",":","str","Determine","how","the","LUT","is","constructed","by","specifying","one","of","the","following",":","*","``","``","kmeans","''","``","(","default",")",":","The","LUT","is","generated","by","`","k-means","clustering","`",",","a","method","of","vector","quantization","that","groups","similar","data","points","together","to","discover","underlying","patterns","by","using","a","fixed","number","(","`","k","`",")","of","clusters","in","a","dataset",".","A","cluster","refers","to","a","collection","of","data","points","aggregated","together","because","of","certain","similarities",".","`","nbits","`","is","required",".","*","``","``","uniform","''","``",":","The","LUT","is","generated","by","a","linear","histogram",".","-","``","[","v_min",",","v_min","+","scale",",","v_min","+","2","*","scale",",","...",",","v_max","]","``","-","Where","the","weight","is","in","the","range","``","[","v_min",",","v_max","]","``",",","and","``","scale","=","(","v_max","-","v_min",")","\/","(","1","<","<","nbits","-","1",")","``",".","-","``","nbits","``","is","required",".","A","`","histogram","`","is","a","representation","of","the","distribution","of","a","continuous","variable",",","in","which","the","entire","range","of","values","is","divided","into","a","series","of","intervals","(","or","`","bins","`",")","and","the","representation","displays","how","many","values","fall","into","each","bin",".","Linear","histograms","have","one","bin","at","even","intervals",",","such","as","one","bin","per","integer",".","*","``","``","unique","''","``",":","The","LUT","is","generated","by","unique","values","in","the","weights",".","The","weights","are","assumed","to","be","on","a","discrete","lattice","but","stored","in","a","float","data","type",".","This","parameter","identifies","the","weights","and","converts","them","into","the","palettized","representation",".","Do","not","provide","``","nbits","``","for","this","mode",".","``","nbits","``","is","picked","up","automatically",",","with","the","smallest","possible","value","in","``","{","1",",","2",",","4",",","6",",","8","}","``","such","that","the","number","of","the","unique","values","is","``","<","=","(","1","<","<","nbits",")","``",".","If","the","weight","has","``",">","256","``","unique","values",",","the","compression","is","skipped",".","For","example",":","*","If","the","weights","are","``","{","0.1",",","0.2",",","0.3",",","0.4","}","``","and","``","nbits=2","``",",","the","weights","are","converted","to","``","{","00b",",","01b",",","10b",",","11b","}","``",",","and","the","generated","LUT","is","``","[","0.1",",","0.2",",","0.3",",","0.4","]","``",".","*","If","the","weights","are","``","{","0.1",",","0.2",",","0.3",",","0.4","}","``","and","``","nbits=1","``",",","nothing","happens","because","the","weights","are","not","a","1-bit","lattice",".","*","If","the","weights","are","``","{","0.1",",","0.2",",","0.3",",","0.4",",","0.5","}","``","and","``","nbits=2","``",",","nothing","happens","because","the","weights","are","not","a","2-bit","lattice",".","*","``","``","custom","''","``",":","The","LUT","and","palettization","parameters","are","calculated","using","a","custom","function",".","If","this","mode","is","selected","then","``","lut_function","``","must","be","provided",".","Do","not","provide","``","nbits","``","for","this","mode",".","The","user","should","customize","``","nbits","``","in","the","``","lut_function","``","implementation",".","lut_function",":","callable","A","callable","function","which","computes","the","weight","palettization","parameters",".","This","must","be","provided","if","the","mode","is","set","to","``","``","custom","''","``",".","weight",":","np.ndarray","A","float","precision","numpy","array",".","Returns",":","lut",":","list","[","float","]","The","lookup","table",".","indices",":","list","[","int","]","A","list","of","indices","for","each","element",".","The","following","is","an","example","that","extract","the","``","top_k","``","elements","as","the","LUT",".","Given","that","``","weight","=","[","0.1",",","0.5",",","0.3",",","0.3",",","0.5",",","0.6",",","0.7","]","``",",","the","``","lut_function","``","produces","``","lut","=","[","0",",","0.5",",","0.6",",","0.7","]",",","indices","=","[","0",",","1",",","0",",","0",",","2",",","3","]","``",".","..","sourcecode",":",":","python","def","lut_function","(","weight",")",":","#","In","this","example",",","we","assume","elements","in","the","weights",">","=","0","weight","=","weight.flatten","(",")","nbits","=","4","#","Get","the","LUT",",","from","extracting","top","k","maximum","unique","elements","in","the","weight","to","be","the","LUT","#","Note","that","k","=","1","<","<","nbits","-","1",",","so","we","have","the","first","element","be","0","unique_elements","=","np.unique","(","weight",")","k","=","(","1","<","<","nbits",")","-","1","top_k","=","np.partition","(","weight",",","-k",")","[","-k",":","]","np.sort","(","top_k",")","lut","=","[","0.0","]","+","top_k.tolist","(",")","#","Compute","the","indices","mapping","=","{","v",":","idx","for","idx",",","v","in","enumerate","(","lut",")","}","indices","=","[","mapping","[","v","]","if","v","in","mapping","else","0","for","v","in","weight","]","return","lut",",","indices","weight_threshold",":","int","The","size","threshold",",","above","which","weights","are","pruned",".","That","is",",","a","weight","tensor","is","pruned","only","if","its","total","number","of","elements","are","greater","than","``","weight_threshold","``",".","For","example",",","if","``","weight_threshold","=","1024","``","and","a","weight","tensor","is","of","shape","``","[","10",",","20",",","1",",","1","]","``",",","hence","``","200","``","elements",",","it","will","not","be","pruned",".","*","If","not","provided",",","it","will","be","set","to","``","2048","``",",","in","which","weights","bigger","than","``","2048","``","elements","are","compressed","."]
code: def check_lut_function(self, attr, lut_function):
      mode = self.mode.upper()
  
      if lut_function is None and mode == "CUSTOM":
          raise ValueError(
              '"lut_function" can not be None, if "mode" is "custom".'
          )
  
      if lut_function is not None and mode != "CUSTOM":
          raise ValueError(
              '"lut_function" must be None, if "mode" is not "custom".'
          )
  
      if lut_function is not None and not callable(lut_function):
          raise ValueError(
              f'A function object must be provided as "lut_function". Got a "lut_function" as type {type(self.lut_function)}'
          )
  
imports: import sys
  from abc import ABC, abstractmethod
  from collections import OrderedDict
  from typing import IO, Any, Callable, Dict, Optional, Tuple, Union
  import cattrs
  import numpy
  import yaml
  from attrs import define, field, validators
  from coremltools.converters.mil.mil import Operation, types
  from coremltools.converters.mil.mil.types.type_mapping import is_builtin, numpy_type_to_builtin_type
label_desc: Use image node_id 3 for calling the OpPalettizerConfig obj's underlying member method code with example usage: obj.check_lut_function(attr, lut_function) without return types