prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Add docs on how to define your own quantizer
  
  
  </issue>
  <code>
  [start of larq/quantizers.py]
  1 """A Quantizer defines the way of transforming a full precision input to a
  2 quantized output and the pseudo-gradient method used for the backwards pass."""
  3 
  4 import tensorflow as tf
  5 from larq import utils
  6 
  7 
  8 def sign(x):
  9     """A sign function that will never be zero"""
  10     return tf.sign(tf.sign(x) + 0.1)
  11 
  12 
  13 @tf.custom_gradient
  14 def _binarize_with_identity_grad(x):
  15     def grad(dy):
  16         return dy
  17 
  18     return sign(x), grad
  19 
  20 
  21 @tf.custom_gradient
  22 def _binarize_with_weighted_grad(x):
  23     def grad(dy):
  24         return (1 - tf.abs(x)) * 2 * dy
  25 
  26     return sign(x), grad
  27 
  28 
  29 @utils.register_keras_custom_object
  30 def ste_sign(x):
  31     r"""
  32     Sign binarization function.
  33     \\[
  34     q(x) = \begin{cases}
  35       -1 & x < 0 \\\
  36       1 & x \geq 0
  37     \end{cases}
  38     \\]
  39 
  40     The gradient is estimated using the Straight-Through Estimator
  41     (essentially the binarization is replaced by a clipped identity on the
  42     backward pass).
  43     \\[\frac{\partial q(x)}{\partial x} = \begin{cases}
  44       1 & \left|x\right| \leq 1 \\\
  45       0 & \left|x\right| > 1
  46     \end{cases}\\]
  47 
  48     # Arguments
  49     x: Input tensor.
  50 
  51     # Returns
  52     Binarized tensor.
  53 
  54     # References
  55     - [Binarized Neural Networks: Training Deep Neural Networks with Weights and
  56       Activations Constrained to +1 or -1](http://arxiv.org/abs/1602.02830)
  57     """
  58 
  59     x = tf.clip_by_value(x, -1, 1)
  60 
  61     return _binarize_with_identity_grad(x)
  62 
  63 
  64 @utils.register_keras_custom_object
  65 def magnitude_aware_sign(x):
  66     r"""
  67     Magnitude-aware sign for birealnet.
  68 
  69 
  70     # Arguments
  71     x: Input tensor
  72 
  73     # Returns
  74     Scaled binarized tensor (with values in $\{-a, a\}$, where $a$ is a float).
  75 
  76     # References
  77     - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved
  78       Representational Capability and Advanced Training
  79       Algorithm](https://arxiv.org/abs/1808.00278)
  80 
  81     """
  82     scale_factor = tf.stop_gradient(
  83         tf.reduce_mean(tf.abs(x), axis=list(range(len(x.shape) - 1)))
  84     )
  85     return scale_factor * ste_sign(x)
  86 
  87 
  88 @utils.register_keras_custom_object
  89 def approx_sign(x):
  90     r"""
  91     Sign binarization function.
  92     \\[
  93     q(x) = \begin{cases}
  94       -1 & x < 0 \\\
  95       1 & x \geq 0
  96    \end{cases}
  97    \\]
  98 
  99     The gradient is estimated using the ApproxSign method.
  100     \\[\frac{\partial q(x)}{\partial x} = \begin{cases}
  101       (2 - 2 \left|x\right|) & \left|x\right| \leq 1 \\\
  102       0 & \left|x\right| > 1
  103     \end{cases}
  104     \\]
  105 
  106     # Arguments
  107     x: Input tensor.
  108 
  109     # Returns
  110     Binarized tensor.
  111 
  112     # References
  113     - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved
  114       Representational Capability and Advanced
  115       Training Algorithm](http://arxiv.org/abs/1808.00278)
  116     """
  117 
  118     x = tf.clip_by_value(x, -1, 1)
  119 
  120     return _binarize_with_weighted_grad(x)
  121 
  122 
  123 def serialize(initializer):
  124     return tf.keras.utils.serialize_keras_object(initializer)
  125 
  126 
  127 def deserialize(name, custom_objects=None):
  128     return tf.keras.utils.deserialize_keras_object(
  129         name,
  130         module_objects=globals(),
  131         custom_objects=custom_objects,
  132         printable_module_name="quantization function",
  133     )
  134 
  135 
  136 def get(identifier):
  137     if identifier is None:
  138         return None
  139     if isinstance(identifier, str):
  140         return deserialize(str(identifier))
  141     if callable(identifier):
  142         return identifier
  143     raise ValueError(
  144         f"Could not interpret quantization function identifier: {identifier}"
  145     )
  146
  [end of larq/quantizers.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/larq/quantizers.py b/larq/quantizers.py
  --- a/larq/quantizers.py
  +++ b/larq/quantizers.py
  @@ -64,7 +64,7 @@
   @utils.register_keras_custom_object
   def magnitude_aware_sign(x):
       r"""
  -    Magnitude-aware sign for birealnet.
  +    Magnitude-aware sign for Bi-Real Net.
   
   
       # Arguments
  
verification_info: {"golden_diff": "diff --git a/larq/quantizers.py b/larq/quantizers.py\n--- a/larq/quantizers.py\n+++ b/larq/quantizers.py\n@@ -64,7 +64,7 @@\n @utils.register_keras_custom_object\n def magnitude_aware_sign(x):\n     r\"\"\"\n-    Magnitude-aware sign for birealnet.\n+    Magnitude-aware sign for Bi-Real Net.\n \n \n     # Arguments\n", "issue": "Add docs on how to define your own quantizer\n\n", "before_files": [{"content": "\"\"\"A Quantizer defines the way of transforming a full precision input to a\nquantized output and the pseudo-gradient method used for the backwards pass.\"\"\"\n\nimport tensorflow as tf\nfrom larq import utils\n\n\ndef sign(x):\n    \"\"\"A sign function that will never be zero\"\"\"\n    return tf.sign(tf.sign(x) + 0.1)\n\n\n@tf.custom_gradient\ndef _binarize_with_identity_grad(x):\n    def grad(dy):\n        return dy\n\n    return sign(x), grad\n\n\n@tf.custom_gradient\ndef _binarize_with_weighted_grad(x):\n    def grad(dy):\n        return (1 - tf.abs(x)) * 2 * dy\n\n    return sign(x), grad\n\n\n@utils.register_keras_custom_object\ndef ste_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n    \\end{cases}\n    \\\\]\n\n    The gradient is estimated using the Straight-Through Estimator\n    (essentially the binarization is replaced by a clipped identity on the\n    backward pass).\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      1 & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Binarized Neural Networks: Training Deep Neural Networks with Weights and\n      Activations Constrained to +1 or -1](http://arxiv.org/abs/1602.02830)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_identity_grad(x)\n\n\n@utils.register_keras_custom_object\ndef magnitude_aware_sign(x):\n    r\"\"\"\n    Magnitude-aware sign for birealnet.\n\n\n    # Arguments\n    x: Input tensor\n\n    # Returns\n    Scaled binarized tensor (with values in $\\{-a, a\\}$, where $a$ is a float).\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced Training\n      Algorithm](https://arxiv.org/abs/1808.00278)\n\n    \"\"\"\n    scale_factor = tf.stop_gradient(\n        tf.reduce_mean(tf.abs(x), axis=list(range(len(x.shape) - 1)))\n    )\n    return scale_factor * ste_sign(x)\n\n\n@utils.register_keras_custom_object\ndef approx_sign(x):\n    r\"\"\"\n    Sign binarization function.\n    \\\\[\n    q(x) = \\begin{cases}\n      -1 & x < 0 \\\\\\\n      1 & x \\geq 0\n   \\end{cases}\n   \\\\]\n\n    The gradient is estimated using the ApproxSign method.\n    \\\\[\\frac{\\partial q(x)}{\\partial x} = \\begin{cases}\n      (2 - 2 \\left|x\\right|) & \\left|x\\right| \\leq 1 \\\\\\\n      0 & \\left|x\\right| > 1\n    \\end{cases}\n    \\\\]\n\n    # Arguments\n    x: Input tensor.\n\n    # Returns\n    Binarized tensor.\n\n    # References\n    - [Bi-Real Net: Enhancing the Performance of 1-bit CNNs With Improved\n      Representational Capability and Advanced\n      Training Algorithm](http://arxiv.org/abs/1808.00278)\n    \"\"\"\n\n    x = tf.clip_by_value(x, -1, 1)\n\n    return _binarize_with_weighted_grad(x)\n\n\ndef serialize(initializer):\n    return tf.keras.utils.serialize_keras_object(initializer)\n\n\ndef deserialize(name, custom_objects=None):\n    return tf.keras.utils.deserialize_keras_object(\n        name,\n        module_objects=globals(),\n        custom_objects=custom_objects,\n        printable_module_name=\"quantization function\",\n    )\n\n\ndef get(identifier):\n    if identifier is None:\n        return None\n    if isinstance(identifier, str):\n        return deserialize(str(identifier))\n    if callable(identifier):\n        return identifier\n    raise ValueError(\n        f\"Could not interpret quantization function identifier: {identifier}\"\n    )\n", "path": "larq/quantizers.py"}]}