class_docstr: The OnnxSchemaChecker class is a checker for ONNX OpSchema and param schema.
  
  It provides methods to check for input compatibility based on the OpSchema. It also
  provides a matching score to indicate how well the OpSchema matches the input and
  kwargs types. A function will be evaluated as perfect match, nearest match eligible,
  or no match.
  
  Here are some common examples in categories:
  
  1. [NOTE: Perfect match]: The number of inputs and attributes are exactly the same as
      the OpSchema. The types of inputs and attributes are exactly the same as the
      OpSchema.
  
      ```python
      inputs = (Tensor[2, 3], Tensor[2, 3])
      attributes = {"alpha": 1.0}
  
      @torch_op("aten::op")
      def aten_op(self: TReal, other: TReal, alpha: float = 1) -> TReal:
          ...
  
      ```
      Result: Perfect match.
  
  2. [NOTE: Optional input]: The dispatcher recognizes optional inputs. However,
      the input can't be ignored. None must be provided.
  
      ```python
      inputs = (Tensor([2, 3]), None)
      attributes = {}
  
      aten_op(X: TTensor, Y: Optional[INT64]):
          ...
      ```
      Result: Perfect match.
      Real example: `aten::convolution`.
  
  3. [NOTE: Different attributes]: If an attribute is provided with value, it's
      a must to match the attribute in function signature.
      ```python
      inputs = (Tensor([2, 3]),)
      attributes = {"a":1, "b":2}
  
      aten_op(X: TTensor, a: int):
          ...
      ```
      Result: No match.
      Real example: `aten::div` vs `aten::div.Tensor_mode`.
  
  4. [NOTE: Default attributes]: Default attribute will fill in the value into
      inputs/attributes.
      ```python
      inputs = (Tensor([2, 3]),)
      attributes = {}
  
      aten_op(X: TTensor, a: int = 3):
          ...
      ```
      Result: Perfect match.
      Real example: `aten::clone`
  
  5. [NOTE: Ignore attribute with None value]: The attributes with None value
      will be ignored in matching.
      ```python
      inputs = (Tensor([2, 3]),)
      attributes = {"a": None}
  
      aten_op(X: TTensor):
          ...
      ```
      Result: Perfect match.
  
      ```python
      inputs = (Tensor([2, 3]),)
      attributes = {"a": None}
  
      aten_op(X: TTensor, a: int = 3):
          ...
      ```
      Result: Nearest match eligible.
  
      Real example: `aten::div` vs `aten::div.Tensor_mode`.
  
  Attributes:
      onnxfunction: The OnnxFunction.
      param_schema: The parameter schema defined in the OnnxFunction.
      op_schema: The ONNX OpSchema.
      type_constraints: The type constraints defined in the OpSchema.
      attributes: The attributes defined in the OpSchema.
      _matching_score: The matching score of the OnnxSchemaChecker .
docstr: Calculate the inputs matching score of the OpSchema requirements to find the nearest match.
  
  Only the functions which have the same number of inputs and attributes as the
  OpSchema are eligible to be a nearest match candidate. Thus, we don't need to
  check the length of inputs and attributes here, and only check the types of
  inputs and attributes.
  
  How the matchsing score is calculated:
      score += 1 if one input/attribute type is in the type constraints.
  
  Limitations:
      None/NoeType/[] could result in zero matches, and the same score of overloads,
      which will be recorded in SARIF.
  
  Args:
      inputs: The input arguments.
      attributes: The input keyword arguments.
  
  Returns:
      True if the inputs match the requirements, False otherwise.
docstr_tok: ["Calculate","the","inputs","matching","score","of","the","OpSchema","requirements","to","find","the","nearest","match",".","Only","the","functions","which","have","the","same","number","of","inputs","and","attributes","as","the","OpSchema","are","eligible","to","be","a","nearest","match","candidate",".","Thus",",","we","do","n't","need","to","check","the","length","of","inputs","and","attributes","here",",","and","only","check","the","types","of","inputs","and","attributes",".","How","the","matchsing","score","is","calculated",":","score","+=","1","if","one","input\/attribute","type","is","in","the","type","constraints",".","Limitations",":","None\/NoeType\/","[","]","could","result","in","zero","matches",",","and","the","same","score","of","overloads",",","which","will","be","recorded","in","SARIF",".","Args",":","inputs",":","The","input","arguments",".","attributes",":","The","input","keyword","arguments",".","Returns",":","True","if","the","inputs","match","the","requirements",",","False","otherwise","."]
code: def _record_matching_score(
      self,
      inputs: Sequence[
          Optional[
              Union[
                  fx_type_utils.TensorLike,
                  str,
                  int,
                  float,
                  bool,
                  list,
                  complex,
              ]
          ]
      ],
      attributes: Dict[str, fx_type_utils.Argument],
  ):
      """Calculate the inputs matching score of the OpSchema requirements to find the nearest match.
  
      Only the functions which have the same number of inputs and attributes as the
      OpSchema are eligible to be a nearest match candidate. Thus, we don't need to
      check the length of inputs and attributes here, and only check the types of
      inputs and attributes.
  
      How the matchsing score is calculated:
          score += 1 if one input/attribute type is in the type constraints.
  
      Limitations:
          None/NoeType/[] could result in zero matches, and the same score of overloads,
          which will be recorded in SARIF.
  
      Args:
          inputs: The input arguments.
          attributes: The input keyword arguments.
  
      Returns:
          True if the inputs match the requirements, False otherwise.
      """
      self._matching_score = 0
      # If they have different length of arguments, the score would be lower to those
      # functions which have the same length of arguments.
      for schema_input, torch_input in zip(
          self.op_schema.inputs, inputs
      ):
          torch_input_compatible_types = _find_onnx_data_type(
              torch_input
          )
          allowed_types = self.type_constraints[schema_input.type_str]
          if allowed_types.intersection(torch_input_compatible_types):
              # If torch_input_compatible_types is in allowed_types
              # of this input defined in the OpSchema, we know the function
              # and the input are compatible
              self._matching_score += 1
      # NOTE: The penalty is applied to those functions which have different attributes.
      for attribute_name, attribute_proto in self.attributes.items():
          attribute = attributes[attribute_name]
          attribute_onnx_type = (
              fx_type_utils.from_python_type_to_onnx_attribute_type(
                  type(attribute)
              )
          )
          if attribute_onnx_type != attribute_proto.type:
              # If the attribute type of the OpSchema and the attribute type don't match,
              # we know the function and the input are not compatible
              self._matching_score -= 1
  
imports: from __future__ import annotations
  import logging
  import operator
  import types
  from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, TYPE_CHECKING, Union
  import torch
  import torch._ops
  import torch.fx
  from torch.onnx._internal import _beartype
  from torch.onnx._internal.fx import diagnostics, registration, type_utils
  from onnxscript.function_libs.torch_lib import graph_building
label_desc: Use image node_id 5 for calling the _OnnxSchemaChecker obj's underlying member method code with example usage: obj._record_matching_score(inputs, attributes) without return types