prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Proposal: Op Registry
  Once we start getting into more complicated passes having knowledge about operators becomes incredibly useful. What I propose is to maintain a registry of operators mapping to a set of descriptors. 
  
  For example let's take a look at the [eliminate_nop_monotone_argmax](https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/eliminate_nop_monotone_argmax.h) pass. Within the pass we have to maintain an unordered set of ops that are monotone. The correct design would be to have a registry which we can ask whether or not if a certain op is monotone. Once such a registry is implemented, passes can be generalized through descriptors, therefore as we add new ops and their respective descriptors our passes naturally scale out.
  
  Some possible descriptors we could have are:
  - monotonic
  - elementwise independent (op works on an individual element without knowledge of other elements, such as log, but not softmax since it requires calculating a sum over an axis)
  - elementwise dependent (softmax, logsoftmax, softmin, softplus)
  - reduction
  - shape transform (e.g. transpose, view)
  
  @houseroad @bddppq What do you guys think?
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `onnx/optimizer.py`
  Content:
  ```
  1 # ATTENTION: The code in this file is highly EXPERIMENTAL.
  2 # Adventurous users should note that the APIs will probably change.
  3 
  4 """onnx optimizer
  5 
  6 This enables users to optimize their models.
  7 """
  8 from __future__ import absolute_import
  9 from __future__ import division
  10 from __future__ import print_function
  11 from __future__ import unicode_literals
  12 
  13 import onnx
  14 import onnx.onnx_cpp2py_export.optimizer as C
  15 from onnx import ModelProto
  16 from typing import Text, Sequence, Optional
  17 
  18 """Apply the optimization on the serialized ModelProto.
  19 
  20 Arguments:
  21     input (ModelProto): model
  22     names (list of string): list of optimization names
  23 
  24 Return:
  25     return (ModelProto) optimized model
  26 
  27 Supported pass names:
  28     -- nop
  29     -- eliminate_identity
  30     -- eliminate_nop_transpose
  31     -- eliminate_nop_pad
  32     -- eliminate_unused_initializer
  33     -- fuse_consecutive_squeezes
  34     -- fuse_consecutive_transposes
  35     -- fuse_add_bias_into_conv
  36     -- fuse_transpose_into_gemm
  37 """
  38 
  39 get_available_passes = C.get_available_passes
  40 
  41 
  42 def optimize(model, passes=None, fixed_point=False):  # type: (ModelProto, Optional[Sequence[Text]], bool) -> ModelProto
  43     if passes is None:
  44         passes = ['eliminate_nop_transpose',
  45                   'eliminate_nop_pad',
  46                   'fuse_consecutive_transposes',
  47                   'fuse_transpose_into_gemm']
  48     if not isinstance(model, ModelProto):
  49         raise ValueError('Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))
  50 
  51     model_str = model.SerializeToString()
  52     if fixed_point:
  53         optimized_model_str = C.optimize_fixedpoint(model_str, passes)
  54     else:
  55         optimized_model_str = C.optimize(model_str, passes)
  56 
  57     return onnx.load_from_string(optimized_model_str)
  58
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/onnx/optimizer.py b/onnx/optimizer.py
  --- a/onnx/optimizer.py
  +++ b/onnx/optimizer.py
  @@ -26,13 +26,23 @@
   
   Supported pass names:
       -- nop
  +    -- eliminate_deadend
       -- eliminate_identity
  -    -- eliminate_nop_transpose
  +    -- eliminate_nop_dropout
  +    -- eliminate_nop_monotone_argmax
       -- eliminate_nop_pad
  +    -- eliminate_nop_transpose
       -- eliminate_unused_initializer
  +    -- extract_constant_to_initializer
  +    -- fuse_add_bias_into_conv
  +    -- fuse_bn_into_conv
  +    -- fuse_consecutive_concats
  +    -- fuse_consecutive_log_softmax
  +    -- fuse_consecutive_reduce_unsqueeze
       -- fuse_consecutive_squeezes
       -- fuse_consecutive_transposes
  -    -- fuse_add_bias_into_conv
  +    -- fuse_matmul_add_bias_into_gemm
  +    -- fuse_pad_into_conv
       -- fuse_transpose_into_gemm
   """
   
  @@ -45,8 +55,10 @@
                     'eliminate_nop_pad',
                     'fuse_consecutive_transposes',
                     'fuse_transpose_into_gemm']
  +
       if not isinstance(model, ModelProto):
  -        raise ValueError('Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))
  +        raise ValueError(
  +            'Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))
   
       model_str = model.SerializeToString()
       if fixed_point:
  
verification_info: {"golden_diff": "diff --git a/onnx/optimizer.py b/onnx/optimizer.py\n--- a/onnx/optimizer.py\n+++ b/onnx/optimizer.py\n@@ -26,13 +26,23 @@\n \n Supported pass names:\n     -- nop\n+    -- eliminate_deadend\n     -- eliminate_identity\n-    -- eliminate_nop_transpose\n+    -- eliminate_nop_dropout\n+    -- eliminate_nop_monotone_argmax\n     -- eliminate_nop_pad\n+    -- eliminate_nop_transpose\n     -- eliminate_unused_initializer\n+    -- extract_constant_to_initializer\n+    -- fuse_add_bias_into_conv\n+    -- fuse_bn_into_conv\n+    -- fuse_consecutive_concats\n+    -- fuse_consecutive_log_softmax\n+    -- fuse_consecutive_reduce_unsqueeze\n     -- fuse_consecutive_squeezes\n     -- fuse_consecutive_transposes\n-    -- fuse_add_bias_into_conv\n+    -- fuse_matmul_add_bias_into_gemm\n+    -- fuse_pad_into_conv\n     -- fuse_transpose_into_gemm\n \"\"\"\n \n@@ -45,8 +55,10 @@\n                   'eliminate_nop_pad',\n                   'fuse_consecutive_transposes',\n                   'fuse_transpose_into_gemm']\n+\n     if not isinstance(model, ModelProto):\n-        raise ValueError('Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))\n+        raise ValueError(\n+            'Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))\n \n     model_str = model.SerializeToString()\n     if fixed_point:\n", "issue": "Proposal: Op Registry\nOnce we start getting into more complicated passes having knowledge about operators becomes incredibly useful. What I propose is to maintain a registry of operators mapping to a set of descriptors. \r\n\r\nFor example let's take a look at the [eliminate_nop_monotone_argmax](https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/eliminate_nop_monotone_argmax.h) pass. Within the pass we have to maintain an unordered set of ops that are monotone. The correct design would be to have a registry which we can ask whether or not if a certain op is monotone. Once such a registry is implemented, passes can be generalized through descriptors, therefore as we add new ops and their respective descriptors our passes naturally scale out.\r\n\r\nSome possible descriptors we could have are:\r\n- monotonic\r\n- elementwise independent (op works on an individual element without knowledge of other elements, such as log, but not softmax since it requires calculating a sum over an axis)\r\n- elementwise dependent (softmax, logsoftmax, softmin, softplus)\r\n- reduction\r\n- shape transform (e.g. transpose, view)\r\n\r\n@houseroad @bddppq What do you guys think?\n", "before_files": [{"content": "# ATTENTION: The code in this file is highly EXPERIMENTAL.\n# Adventurous users should note that the APIs will probably change.\n\n\"\"\"onnx optimizer\n\nThis enables users to optimize their models.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport onnx\nimport onnx.onnx_cpp2py_export.optimizer as C\nfrom onnx import ModelProto\nfrom typing import Text, Sequence, Optional\n\n\"\"\"Apply the optimization on the serialized ModelProto.\n\nArguments:\n    input (ModelProto): model\n    names (list of string): list of optimization names\n\nReturn:\n    return (ModelProto) optimized model\n\nSupported pass names:\n    -- nop\n    -- eliminate_identity\n    -- eliminate_nop_transpose\n    -- eliminate_nop_pad\n    -- eliminate_unused_initializer\n    -- fuse_consecutive_squeezes\n    -- fuse_consecutive_transposes\n    -- fuse_add_bias_into_conv\n    -- fuse_transpose_into_gemm\n\"\"\"\n\nget_available_passes = C.get_available_passes\n\n\ndef optimize(model, passes=None, fixed_point=False):  # type: (ModelProto, Optional[Sequence[Text]], bool) -> ModelProto\n    if passes is None:\n        passes = ['eliminate_nop_transpose',\n                  'eliminate_nop_pad',\n                  'fuse_consecutive_transposes',\n                  'fuse_transpose_into_gemm']\n    if not isinstance(model, ModelProto):\n        raise ValueError('Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))\n\n    model_str = model.SerializeToString()\n    if fixed_point:\n        optimized_model_str = C.optimize_fixedpoint(model_str, passes)\n    else:\n        optimized_model_str = C.optimize(model_str, passes)\n\n    return onnx.load_from_string(optimized_model_str)\n", "path": "onnx/optimizer.py"}], "after_files": [{"content": "# ATTENTION: The code in this file is highly EXPERIMENTAL.\n# Adventurous users should note that the APIs will probably change.\n\n\"\"\"onnx optimizer\n\nThis enables users to optimize their models.\n\"\"\"\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\nfrom __future__ import unicode_literals\n\nimport onnx\nimport onnx.onnx_cpp2py_export.optimizer as C\nfrom onnx import ModelProto\nfrom typing import Text, Sequence, Optional\n\n\"\"\"Apply the optimization on the serialized ModelProto.\n\nArguments:\n    input (ModelProto): model\n    names (list of string): list of optimization names\n\nReturn:\n    return (ModelProto) optimized model\n\nSupported pass names:\n    -- nop\n    -- eliminate_deadend\n    -- eliminate_identity\n    -- eliminate_nop_dropout\n    -- eliminate_nop_monotone_argmax\n    -- eliminate_nop_pad\n    -- eliminate_nop_transpose\n    -- eliminate_unused_initializer\n    -- extract_constant_to_initializer\n    -- fuse_add_bias_into_conv\n    -- fuse_bn_into_conv\n    -- fuse_consecutive_concats\n    -- fuse_consecutive_log_softmax\n    -- fuse_consecutive_reduce_unsqueeze\n    -- fuse_consecutive_squeezes\n    -- fuse_consecutive_transposes\n    -- fuse_matmul_add_bias_into_gemm\n    -- fuse_pad_into_conv\n    -- fuse_transpose_into_gemm\n\"\"\"\n\nget_available_passes = C.get_available_passes\n\n\ndef optimize(model, passes=None, fixed_point=False):  # type: (ModelProto, Optional[Sequence[Text]], bool) -> ModelProto\n    if passes is None:\n        passes = ['eliminate_nop_transpose',\n                  'eliminate_nop_pad',\n                  'fuse_consecutive_transposes',\n                  'fuse_transpose_into_gemm']\n\n    if not isinstance(model, ModelProto):\n        raise ValueError(\n            'Optimizer only accepts ModelProto, incorrect type: {}'.format(type(model)))\n\n    model_str = model.SerializeToString()\n    if fixed_point:\n        optimized_model_str = C.optimize_fixedpoint(model_str, passes)\n    else:\n        optimized_model_str = C.optimize(model_str, passes)\n\n    return onnx.load_from_string(optimized_model_str)\n", "path": "onnx/optimizer.py"}]}