

'''simple docstring'''







import logging
import re

import pytorch_quantization
import pytorch_quantization.nn as quant_nn
import torch
from pytorch_quantization import calib
from pytorch_quantization.tensor_quant import QuantDescriptor


__lowerCamelCase		       =    logging.getLogger(__name__)

__lowerCamelCase		       =    50  # max width of layer names
__lowerCamelCase		       =    70  # max width of quantizer names
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			Tuple:
       A_						=      parser.add_argument_group("""quant_trainer arguments"""				)
       group.add_argument("""--wprec""",       type=UpperCAmelCase__,       default=8,       help="""weight precision"""				)
       group.add_argument("""--aprec""",       type=UpperCAmelCase__,       default=8,       help="""activation precision"""				)
       group.add_argument("""--quant-per-tensor""",       action="""store_true""",       help="""per tensor weight scaling"""				)
       group.add_argument("""--quant-disable""",       action="""store_true""",       help="""disable all quantizers"""				)
       group.add_argument("""--quant-disable-embeddings""",       action="""store_true""",       help="""disable all embeddings quantizers"""				)
       group.add_argument("""--quant-disable-keyword""",       type=UpperCAmelCase__,       nargs="""+""",       help="""disable quantizers by keyword"""				)
       group.add_argument("""--quant-disable-layer-module""",       type=UpperCAmelCase__,       help="""disable quantizers by keyword under layer."""				)
       group.add_argument("""--quant-enable-layer-module""",       type=UpperCAmelCase__,       help="""enable quantizers by keyword under layer"""				)
       group.add_argument("""--calibrator""",       default="""max""",       help="""which quantization range calibrator to use"""				)
       group.add_argument("""--percentile""",       default=UpperCAmelCase__,       type=UpperCAmelCase__,       help="""percentile for PercentileCalibrator"""				)
       group.add_argument("""--fuse-qkv""",       action="""store_true""",       help="""use the same scale factor for qkv"""				)
       group.add_argument("""--clip-gelu""",       metavar="""N""",       type=UpperCAmelCase__,       help="""clip gelu output maximum value to N"""				)
       group.add_argument(
           """--recalibrate-weights""",       action="""store_true""",       help=(
               """recalibrate weight amaxes by taking the max of the weights."""
               """ amaxes will be computed with the current quantization granularity (axis)."""
           ),       )
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			Optional[Any]:

       if args.calibrator == "max":
              A_						=      """max"""
       elif args.calibrator == "percentile":
              if args.percentile is None:
                     raise ValueError("""Specify --percentile when using percentile calibrator"""				)
              A_						=      """histogram"""
       elif args.calibrator == "mse":
              A_						=      """histogram"""
       else:
              raise ValueError(F'''Invalid calibrator {args.calibrator}'''				)

       A_						=      QuantDescriptor(num_bits=args.aprec,       calib_method=UpperCAmelCase__				)
       A_						=      QuantDescriptor(num_bits=args.wprec,       axis=(None if args.quant_per_tensor else (0,))				)
       quant_nn.QuantLinear.set_default_quant_desc_input(UpperCAmelCase__				)
       quant_nn.QuantLinear.set_default_quant_desc_weight(UpperCAmelCase__				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__=False,       UpperCAmelCase__=False				)			->			Optional[Any]:
       logger.info("""Configuring Model for Quantization"""				)
       logger.info(F'''using quantization package {pytorch_quantization.__file__}'''				)

       if not calib:
              if args.quant_disable_embeddings:
                     set_quantizer_by_name(UpperCAmelCase__,       ["""embeddings"""],       which="""weight""",       _disabled=UpperCAmelCase__				)

              if args.quant_disable:
                     set_quantizer_by_name(UpperCAmelCase__,       [""""""],       _disabled=UpperCAmelCase__				)

              if args.quant_disable_keyword:
                     set_quantizer_by_name(UpperCAmelCase__,       args.quant_disable_keyword,       _disabled=UpperCAmelCase__				)

              if args.quant_disable_layer_module:
                     set_quantizer_by_name(UpperCAmelCase__,       [r"""layer.\d+.""" + args.quant_disable_layer_module],       _disabled=UpperCAmelCase__				)

              if args.quant_enable_layer_module:
                     set_quantizer_by_name(UpperCAmelCase__,       [r"""layer.\d+.""" + args.quant_enable_layer_module],       _disabled=UpperCAmelCase__				)

              if args.recalibrate_weights:
                     recalibrate_weights(UpperCAmelCase__				)

              if args.fuse_qkv:
                     fuse_qkv(UpperCAmelCase__,       UpperCAmelCase__				)

       if args.clip_gelu:
              clip_gelu(UpperCAmelCase__,       args.clip_gelu				)

       # if args.local_rank in [-1, 0] and not calib:
       print_quant_summary(UpperCAmelCase__				)
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			Union[str, Any]:
       logger.info("""Enabling Calibration"""				)
       for name, module in model.named_modules():
              if name.endswith("""_quantizer"""				):
                     if module._calibrator is not None:
                            module.disable_quant()
                            module.enable_calib()
                     else:
                            module.disable()
                     logger.info(F'''{name:80}: {module}'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__				)			->			Optional[Any]:
       logger.info("""Loading calibrated amax"""				)
       for name, module in model.named_modules():
              if name.endswith("""_quantizer"""				):
                     if module._calibrator is not None:
                            if isinstance(module._calibrator,       calib.MaxCalibrator				):
                                   module.load_calib_amax()
                            else:
                                   module.load_calib_amax("""percentile""",       percentile=args.percentile				)
                            module.enable_quant()
                            module.disable_calib()
                     else:
                            module.enable()
       model.cuda()
       print_quant_summary(UpperCAmelCase__				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__				)			->			Tuple:

       def fusea(UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				):
              for mod in [qq, qk, qv]:
                     if not hasattr(UpperCAmelCase__,       """_amax"""				):
                            print("""          WARNING: NO AMAX BUFFER"""				)
                            return
              A_						=      qq._amax.detach().item()
              A_						=      qk._amax.detach().item()
              A_						=      qv._amax.detach().item()

              A_						=      max(UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)
              qq._amax.fill_(UpperCAmelCase__				)
              qk._amax.fill_(UpperCAmelCase__				)
              qv._amax.fill_(UpperCAmelCase__				)
              logger.info(F'''          q={q:5.2f} k={k:5.2f} v={v:5.2f} -> {amax:5.2f}'''				)

       for name, mod in model.named_modules():
              if name.endswith(""".attention.self"""				):
                     logger.info(F'''FUSE_QKV: {name:{name_width}}'''				)
                     fusea(mod.matmul_q_input_quantizer,       mod.matmul_k_input_quantizer,       mod.matmul_v_input_quantizer				)
                     if args.quant_per_tensor:
                            fusea(mod.query._weight_quantizer,       mod.key._weight_quantizer,       mod.value._weight_quantizer				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__				)			->			List[Any]:

       for name, mod in model.named_modules():
              if name.endswith(""".output.dense"""				) and not name.endswith("""attention.output.dense"""				):
                     A_						=      mod._input_quantizer._amax.data.detach().item()
                     mod._input_quantizer._amax.data.detach().clamp_(max=UpperCAmelCase__				)
                     A_						=      mod._input_quantizer._amax.data.detach().item()
                     logger.info(F'''CLIP_GELU: {name:{name_width}} amax: {amax_init:5.2f} -> {amax:5.2f}'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			Dict:

       for name, mod in model.named_modules():
              if hasattr(UpperCAmelCase__,       """_weight_quantizer"""				) and mod._weight_quantizer.axis is not None:
                     A_						=      mod.weight.shape[0]
                     A_						=      mod._weight_quantizer._amax.detach()
                     A_						=      torch.ones(UpperCAmelCase__,       dtype=amax.dtype,       device=amax.device				) * amax
                     print(F'''expanding {name} {amax} -> {mod._weight_quantizer._amax}'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			Union[str, Any]:

       for name, mod in model.named_modules():
              if hasattr(UpperCAmelCase__,       """_weight_quantizer"""				):
                     if not hasattr(mod.weight_quantizer,       """_amax"""				):
                            print("""RECALIB: {name:{name_width}} WARNING: NO AMAX BUFFER"""				)
                            continue

                     # determine which axes to reduce across
                     # e.g. a 4D tensor quantized per axis 0 should reduce over (1,2,3)
                     A_						=      set() if mod._weight_quantizer.axis is None else set(mod._weight_quantizer.axis				)
                     A_						=      set(range(len(mod.weight.size()				)				)				) - axis_set
                     A_						=      pytorch_quantization.utils.reduce_amax(mod.weight,       axis=UpperCAmelCase__,       keepdims=UpperCAmelCase__				).detach()
                     logger.info(F'''RECALIB: {name:{name_width}} {mod._weight_quantizer._amax.flatten()} -> {amax.flatten()}'''				)
                     A_						=      amax
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__=25,       UpperCAmelCase__=1_80,       UpperCAmelCase__=None				)			->			Optional[int]:

       if ignore is None:
              A_						=      []
       elif not isinstance(UpperCAmelCase__,       UpperCAmelCase__				):
              A_						=      [ignore]

       A_						=      0
       for name, mod in model.named_modules():
              if not hasattr(UpperCAmelCase__,       """weight"""				):
                     continue
              A_						=      max(UpperCAmelCase__,       len(UpperCAmelCase__				)				)

       for name, mod in model.named_modules():
              A_						=      getattr(UpperCAmelCase__,       """_input_quantizer""",       UpperCAmelCase__				)
              A_						=      getattr(UpperCAmelCase__,       """_weight_quantizer""",       UpperCAmelCase__				)
              if not hasattr(UpperCAmelCase__,       """weight"""				):
                     continue
              if type(UpperCAmelCase__				) in ignore:
                     continue
              if [True for s in ignore if type(UpperCAmelCase__				) is str and s in name]:
                     continue
              A_						=      F'''Act:{input_q.extra_repr()}'''
              A_						=      F'''Wgt:{weight_q.extra_repr()}'''
              A_						=      F'''{name:{name_width}} {act_str} {wgt_str}'''
              if len(UpperCAmelCase__				) <= line_width:
                     logger.info(UpperCAmelCase__				)
              else:
                     logger.info(F'''{name:{name_width}} {act_str}'''				)
                     logger.info(F'''{"  ":{name_width}} {wgt_str}'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			str:
       A_						=      0
       for name, mod in model.named_modules():
              if isinstance(UpperCAmelCase__,       pytorch_quantization.nn.TensorQuantizer				):
                     print(F'''{name:80} {mod}'''				)
                     count += 1
       print(F'''{count} TensorQuantizers found in model'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)			->			str:
       A_						=      getattr(UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)
       if quantizer_mod is not None:
              assert hasattr(UpperCAmelCase__,       UpperCAmelCase__				)
              setattr(UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)
       else:
              logger.warning(F'''{name} has no {quantizer}'''				)
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__="both",       **UpperCAmelCase__				)			->			Any:
       A_						=      F'''Warning: changing {which} quantizers of {name:{qname_width}}'''
       for k, v in kwargs.items():
              s += F''' {k}={v}'''
              if which in ["input", "both"]:
                     set_quantizer(UpperCAmelCase__,       UpperCAmelCase__,       """_input_quantizer""",       UpperCAmelCase__,       UpperCAmelCase__				)
              if which in ["weight", "both"]:
                     set_quantizer(UpperCAmelCase__,       UpperCAmelCase__,       """_weight_quantizer""",       UpperCAmelCase__,       UpperCAmelCase__				)
       logger.info(UpperCAmelCase__				)







def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__,       **UpperCAmelCase__				)			->			Optional[Any]:

       for name, mod in model.named_modules():
              if hasattr(UpperCAmelCase__,       """_input_quantizer"""				) or hasattr(UpperCAmelCase__,       """_weight_quantizer"""				):
                     for n in names:
                            if re.search(UpperCAmelCase__,       UpperCAmelCase__				):
                                   set_quantizers(UpperCAmelCase__,       UpperCAmelCase__,       **UpperCAmelCase__				)
              elif name.endswith("""_quantizer"""				):
                     for n in names:
                            if re.search(UpperCAmelCase__,       UpperCAmelCase__				):
                                   A_						=      F'''Warning: changing {name:{name_width}}'''
                                   for k, v in kwargs.items():
                                          s += F''' {k}={v}'''
                                          setattr(UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)
                                   logger.info(UpperCAmelCase__				)



'''simple docstring'''







import os

__lowerCamelCase		       =    {'''I''': 1, '''V''': 5, '''X''': 10, '''L''': 50, '''C''': 100, '''D''': 500, '''M''': 1000}
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			int:
       A_						=      0

       A_						=      0
       while index < len(UpperCAmelCase__				) - 1:
              A_						=      SYMBOLS[numerals[index]]
              A_						=      SYMBOLS[numerals[index + 1]]
              if current_value < next_value:
                     total_value -= current_value
              else:
                     total_value += current_value
              index += 1
       total_value += SYMBOLS[numerals[index]]

       return total_value
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			str:
       A_						=      """"""

       A_						=      num // 10_00
       numerals += m_count * "M"
       num %= 10_00

       A_						=      num // 1_00
       if c_count == 9:
              numerals += "CM"
              c_count -= 9
       elif c_count == 4:
              numerals += "CD"
              c_count -= 4
       if c_count >= 5:
              numerals += "D"
              c_count -= 5
       numerals += c_count * "C"
       num %= 1_00

       A_						=      num // 10
       if x_count == 9:
              numerals += "XC"
              x_count -= 9
       elif x_count == 4:
              numerals += "XL"
              x_count -= 4
       if x_count >= 5:
              numerals += "L"
              x_count -= 5
       numerals += x_count * "X"
       num %= 10

       if num == 9:
              numerals += "IX"
              num -= 9
       elif num == 4:
              numerals += "IV"
              num -= 4
       if num >= 5:
              numerals += "V"
              num -= 5
       numerals += num * "I"

       return numerals
def       UpperCAmelCase__    (      UpperCAmelCase__ = "/p089_roman.txt"				)			->			int:
       A_						=      0

       with open(os.path.dirname(UpperCAmelCase__				) + roman_numerals_filename				) as filea:
              A_						=      filea.readlines()

       for line in lines:
              A_						=      line.strip()
              A_						=      parse_roman_numerals(UpperCAmelCase__				)
              A_						=      generate_roman_numerals(UpperCAmelCase__				)
              savings += len(UpperCAmelCase__				) - len(UpperCAmelCase__				)

       return savings


if __name__ == "__main__":
      print(f"""{solution() = }""")
