prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Bug in recursive attach of MetricsLambda
  As a result of #385, the recursive attach of MetricsLambda is not working as intended. 
  
  The code below throws this error: `NotComputableError: Accuracy must have at least one example before it can be computed.`
  
  ```python
  import torch
  
  from ignite.metrics import Accuracy, Precision, Recall, MetricsLambda
  from ignite.engine import Engine
  
  accuracy_1 = Accuracy()
  accuracy_2 = Accuracy()
  mean_accuracy = (accuracy_1 + accuracy_2) / 2
  
  
  metrics = {
  #     "a1": accuracy_1,
  #     "a2": accuracy_2,    
      "mean accuracy": mean_accuracy,
  }
  
  
  y_pred = torch.randint(0, 2, size=(15, 10, 4)).float()
  y = torch.randint(0, 2, size=(15, 10, 4)).long()
  
  def update_fn(engine, batch):
      y_pred, y = batch
      return y_pred, y
  
  validator = Engine(update_fn)
  
  for name, metric in metrics.items():
      metric.attach(validator, name)
  
  def data(y_pred, y):
      for i in range(y_pred.shape[0]):
          yield (y_pred[i], y[i])
  
  d = data(y_pred, y)
  state = validator.run(d, max_epochs=1)
  
  print(state.metrics)
  ```
  
  cc @vfdev-5 @amitibo 
  
  </issue>
  <code>
  [start of ignite/metrics/metrics_lambda.py]
  1 from ignite.metrics.metric import Metric
  2 from ignite.engine import Events
  3 
  4 
  5 class MetricsLambda(Metric):
  6     """
  7     Apply a function to other metrics to obtain a new metric.
  8     The result of the new metric is defined to be the result
  9     of applying the function to the result of argument metrics.
  10 
  11     When update, this metric does not recursively update the metrics
  12     it depends on. When reset, all its dependency metrics would be
  13     resetted. When attach, all its dependencies would be automatically
  14     attached.
  15 
  16     Args:
  17         f (callable): the function that defines the computation
  18         args (sequence): Sequence of other metrics or something
  19             else that will be fed to ``f`` as arguments.
  20 
  21     Example:
  22 
  23     .. code-block:: python
  24 
  25         precision = Precision(average=False)
  26         recall = Recall(average=False)
  27 
  28         def Fbeta(r, p, beta):
  29             return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()
  30 
  31         F1 = MetricsLambda(Fbeta, recall, precision, 1)
  32         F2 = MetricsLambda(Fbeta, recall, precision, 2)
  33         F3 = MetricsLambda(Fbeta, recall, precision, 3)
  34         F4 = MetricsLambda(Fbeta, recall, precision, 4)
  35     """
  36     def __init__(self, f, *args):
  37         self.function = f
  38         self.args = args
  39         super(MetricsLambda, self).__init__()
  40 
  41     def reset(self):
  42         for i in self.args:
  43             if isinstance(i, Metric):
  44                 i.reset()
  45 
  46     def update(self, output):
  47         # NB: this method does not recursively update dependency metrics,
  48         # which might cause duplicate update issue. To update this metric,
  49         # users should manually update its dependencies.
  50         pass
  51 
  52     def compute(self):
  53         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]
  54         return self.function(*materialized)
  55 
  56     def attach(self, engine, name):
  57         # recursively attach all its dependencies
  58         for index, metric in enumerate(self.args):
  59             if isinstance(metric, Metric):
  60                 if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):
  61                     engine.add_event_handler(Events.EPOCH_STARTED, metric.started)
  62                 if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):
  63                     engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)
  64         super(MetricsLambda, self).attach(engine, name)
  65
  [end of ignite/metrics/metrics_lambda.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/ignite/metrics/metrics_lambda.py b/ignite/metrics/metrics_lambda.py
  --- a/ignite/metrics/metrics_lambda.py
  +++ b/ignite/metrics/metrics_lambda.py
  @@ -53,12 +53,18 @@
           materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]
           return self.function(*materialized)
   
  -    def attach(self, engine, name):
  -        # recursively attach all its dependencies
  +    def _internal_attach(self, engine):
           for index, metric in enumerate(self.args):
  -            if isinstance(metric, Metric):
  +            if isinstance(metric, MetricsLambda):
  +                metric._internal_attach(engine)
  +            elif isinstance(metric, Metric):
                   if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):
                       engine.add_event_handler(Events.EPOCH_STARTED, metric.started)
                   if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):
                       engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)
  -        super(MetricsLambda, self).attach(engine, name)
  +
  +    def attach(self, engine, name):
  +        # recursively attach all its dependencies
  +        self._internal_attach(engine)
  +        # attach only handler on EPOCH_COMPLETED
  +        engine.add_event_handler(Events.EPOCH_COMPLETED, self.completed, name)
  
verification_info: {"golden_diff": "diff --git a/ignite/metrics/metrics_lambda.py b/ignite/metrics/metrics_lambda.py\n--- a/ignite/metrics/metrics_lambda.py\n+++ b/ignite/metrics/metrics_lambda.py\n@@ -53,12 +53,18 @@\n         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]\n         return self.function(*materialized)\n \n-    def attach(self, engine, name):\n-        # recursively attach all its dependencies\n+    def _internal_attach(self, engine):\n         for index, metric in enumerate(self.args):\n-            if isinstance(metric, Metric):\n+            if isinstance(metric, MetricsLambda):\n+                metric._internal_attach(engine)\n+            elif isinstance(metric, Metric):\n                 if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):\n                     engine.add_event_handler(Events.EPOCH_STARTED, metric.started)\n                 if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):\n                     engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)\n-        super(MetricsLambda, self).attach(engine, name)\n+\n+    def attach(self, engine, name):\n+        # recursively attach all its dependencies\n+        self._internal_attach(engine)\n+        # attach only handler on EPOCH_COMPLETED\n+        engine.add_event_handler(Events.EPOCH_COMPLETED, self.completed, name)\n", "issue": "Bug in recursive attach of MetricsLambda\nAs a result of #385, the recursive attach of MetricsLambda is not working as intended. \r\n\r\nThe code below throws this error: `NotComputableError: Accuracy must have at least one example before it can be computed.`\r\n\r\n```python\r\nimport torch\r\n\r\nfrom ignite.metrics import Accuracy, Precision, Recall, MetricsLambda\r\nfrom ignite.engine import Engine\r\n\r\naccuracy_1 = Accuracy()\r\naccuracy_2 = Accuracy()\r\nmean_accuracy = (accuracy_1 + accuracy_2) / 2\r\n\r\n\r\nmetrics = {\r\n#     \"a1\": accuracy_1,\r\n#     \"a2\": accuracy_2,    \r\n    \"mean accuracy\": mean_accuracy,\r\n}\r\n\r\n\r\ny_pred = torch.randint(0, 2, size=(15, 10, 4)).float()\r\ny = torch.randint(0, 2, size=(15, 10, 4)).long()\r\n\r\ndef update_fn(engine, batch):\r\n    y_pred, y = batch\r\n    return y_pred, y\r\n\r\nvalidator = Engine(update_fn)\r\n\r\nfor name, metric in metrics.items():\r\n    metric.attach(validator, name)\r\n\r\ndef data(y_pred, y):\r\n    for i in range(y_pred.shape[0]):\r\n        yield (y_pred[i], y[i])\r\n\r\nd = data(y_pred, y)\r\nstate = validator.run(d, max_epochs=1)\r\n\r\nprint(state.metrics)\r\n```\r\n\r\ncc @vfdev-5 @amitibo \n", "before_files": [{"content": "from ignite.metrics.metric import Metric\nfrom ignite.engine import Events\n\n\nclass MetricsLambda(Metric):\n    \"\"\"\n    Apply a function to other metrics to obtain a new metric.\n    The result of the new metric is defined to be the result\n    of applying the function to the result of argument metrics.\n\n    When update, this metric does not recursively update the metrics\n    it depends on. When reset, all its dependency metrics would be\n    resetted. When attach, all its dependencies would be automatically\n    attached.\n\n    Args:\n        f (callable): the function that defines the computation\n        args (sequence): Sequence of other metrics or something\n            else that will be fed to ``f`` as arguments.\n\n    Example:\n\n    .. code-block:: python\n\n        precision = Precision(average=False)\n        recall = Recall(average=False)\n\n        def Fbeta(r, p, beta):\n            return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()\n\n        F1 = MetricsLambda(Fbeta, recall, precision, 1)\n        F2 = MetricsLambda(Fbeta, recall, precision, 2)\n        F3 = MetricsLambda(Fbeta, recall, precision, 3)\n        F4 = MetricsLambda(Fbeta, recall, precision, 4)\n    \"\"\"\n    def __init__(self, f, *args):\n        self.function = f\n        self.args = args\n        super(MetricsLambda, self).__init__()\n\n    def reset(self):\n        for i in self.args:\n            if isinstance(i, Metric):\n                i.reset()\n\n    def update(self, output):\n        # NB: this method does not recursively update dependency metrics,\n        # which might cause duplicate update issue. To update this metric,\n        # users should manually update its dependencies.\n        pass\n\n    def compute(self):\n        materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]\n        return self.function(*materialized)\n\n    def attach(self, engine, name):\n        # recursively attach all its dependencies\n        for index, metric in enumerate(self.args):\n            if isinstance(metric, Metric):\n                if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):\n                    engine.add_event_handler(Events.EPOCH_STARTED, metric.started)\n                if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):\n                    engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)\n        super(MetricsLambda, self).attach(engine, name)\n", "path": "ignite/metrics/metrics_lambda.py"}]}