prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Improve MetricLambda implementation
  User can get the following output in the `state.metrics`:
  ```
  {'accuracy': 0.37127896829244644,
   'error': 0.6287210317075536,
   'error[0]': -0.6287210317075536,
   'error[0][0]': 0.37127896829244644,
  ```
  when launch the below code:
  ```python
  accuracy_metric = Accuracy()
  error_metric = (accuracy_metric - 1.0) * (-1.0)
  
  metrics = {
      "accuracy": accuracy_metric,
      "error": error_metric,
  }
  
  validator = create_supervised_evaluator(model, metrics=metrics)
  validator.run(val_loader, max_epochs=1)
  print(validator.state.metrics)
  ```
  
  This is due to 
  
  https://github.com/pytorch/ignite/blob/d9820451da779e0d0c393804db381e5483240b1c/ignite/metrics/metrics_lambda.py#L50-L54
  
  and 
  
  https://github.com/pytorch/ignite/blob/d9820451da779e0d0c393804db381e5483240b1c/ignite/metrics/metric.py#L68
  
  IMO, user is not interested of this internal info used to compute `error_metric`. We can add some special characters to ignore the result of compute when insert to `engine.state.metrics[name]`.
  
  cc @zasdfgbnm 
  
  </issue>
  <code>
  [start of ignite/metrics/metrics_lambda.py]
  1 from ignite.metrics.metric import Metric
  2 
  3 
  4 class MetricsLambda(Metric):
  5     """
  6     Apply a function to other metrics to obtain a new metric.
  7     The result of the new metric is defined to be the result
  8     of applying the function to the result of argument metrics.
  9 
  10     When update, this metric does not recursively update the metrics
  11     it depends on. When reset, all its dependency metrics would be
  12     resetted. When attach, all its dependencies would be automatically
  13     attached.
  14 
  15     Arguments:
  16         f (callable): the function that defines the computation
  17         args (sequence): Sequence of other metrics or something
  18             else that will be fed to ``f`` as arguments.
  19 
  20     Examples:
  21         >>> precision = Precision(average=False)
  22         >>> recall = Recall(average=False)
  23         >>> def Fbeta(r, p, beta):
  24         >>>     return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r)).item()
  25         >>> F1 = MetricsLambda(Fbeta, recall, precision, 1)
  26         >>> F2 = MetricsLambda(Fbeta, recall, precision, 2)
  27         >>> F3 = MetricsLambda(Fbeta, recall, precision, 3)
  28         >>> F4 = MetricsLambda(Fbeta, recall, precision, 4)
  29     """
  30     def __init__(self, f, *args):
  31         self.function = f
  32         self.args = args
  33         super(MetricsLambda, self).__init__()
  34 
  35     def reset(self):
  36         for i in self.args:
  37             if isinstance(i, Metric):
  38                 i.reset()
  39 
  40     def update(self, output):
  41         # NB: this method does not recursively update dependency metrics,
  42         # which might cause duplicate update issue. To update this metric,
  43         # users should manually update its dependencies.
  44         pass
  45 
  46     def compute(self):
  47         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]
  48         return self.function(*materialized)
  49 
  50     def attach(self, engine, name):
  51         # recursively attach all its dependencies
  52         for index, metric in enumerate(self.args):
  53             if isinstance(metric, Metric):
  54                 metric.attach(engine, name + '[{}]'.format(index))
  55         super(MetricsLambda, self).attach(engine, name)
  56
  [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
  @@ -1,4 +1,5 @@
   from ignite.metrics.metric import Metric
  +from ignite.engine import Events
   
   
   class MetricsLambda(Metric):
  @@ -12,20 +13,25 @@
       resetted. When attach, all its dependencies would be automatically
       attached.
   
  -    Arguments:
  +    Args:
           f (callable): the function that defines the computation
           args (sequence): Sequence of other metrics or something
               else that will be fed to ``f`` as arguments.
   
  -    Examples:
  -        >>> precision = Precision(average=False)
  -        >>> recall = Recall(average=False)
  -        >>> def Fbeta(r, p, beta):
  -        >>>     return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r)).item()
  -        >>> F1 = MetricsLambda(Fbeta, recall, precision, 1)
  -        >>> F2 = MetricsLambda(Fbeta, recall, precision, 2)
  -        >>> F3 = MetricsLambda(Fbeta, recall, precision, 3)
  -        >>> F4 = MetricsLambda(Fbeta, recall, precision, 4)
  +    Example:
  +
  +    .. code-block:: python
  +
  +        precision = Precision(average=False)
  +        recall = Recall(average=False)
  +
  +        def Fbeta(r, p, beta):
  +            return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()
  +
  +        F1 = MetricsLambda(Fbeta, recall, precision, 1)
  +        F2 = MetricsLambda(Fbeta, recall, precision, 2)
  +        F3 = MetricsLambda(Fbeta, recall, precision, 3)
  +        F4 = MetricsLambda(Fbeta, recall, precision, 4)
       """
       def __init__(self, f, *args):
           self.function = f
  @@ -51,5 +57,8 @@
           # recursively attach all its dependencies
           for index, metric in enumerate(self.args):
               if isinstance(metric, Metric):
  -                metric.attach(engine, name + '[{}]'.format(index))
  +                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)
  
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@@ -1,4 +1,5 @@\n from ignite.metrics.metric import Metric\n+from ignite.engine import Events\n \n \n class MetricsLambda(Metric):\n@@ -12,20 +13,25 @@\n     resetted. When attach, all its dependencies would be automatically\n     attached.\n \n-    Arguments:\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-    Examples:\n-        >>> precision = Precision(average=False)\n-        >>> recall = Recall(average=False)\n-        >>> def Fbeta(r, p, beta):\n-        >>>     return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r)).item()\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+    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@@ -51,5 +57,8 @@\n         # recursively attach all its dependencies\n         for index, metric in enumerate(self.args):\n             if isinstance(metric, Metric):\n-                metric.attach(engine, name + '[{}]'.format(index))\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", "issue": "Improve MetricLambda implementation\nUser can get the following output in the `state.metrics`:\r\n```\r\n{'accuracy': 0.37127896829244644,\r\n 'error': 0.6287210317075536,\r\n 'error[0]': -0.6287210317075536,\r\n 'error[0][0]': 0.37127896829244644,\r\n```\r\nwhen launch the below code:\r\n```python\r\naccuracy_metric = Accuracy()\r\nerror_metric = (accuracy_metric - 1.0) * (-1.0)\r\n\r\nmetrics = {\r\n    \"accuracy\": accuracy_metric,\r\n    \"error\": error_metric,\r\n}\r\n\r\nvalidator = create_supervised_evaluator(model, metrics=metrics)\r\nvalidator.run(val_loader, max_epochs=1)\r\nprint(validator.state.metrics)\r\n```\r\n\r\nThis is due to \r\n\r\nhttps://github.com/pytorch/ignite/blob/d9820451da779e0d0c393804db381e5483240b1c/ignite/metrics/metrics_lambda.py#L50-L54\r\n\r\nand \r\n\r\nhttps://github.com/pytorch/ignite/blob/d9820451da779e0d0c393804db381e5483240b1c/ignite/metrics/metric.py#L68\r\n\r\nIMO, user is not interested of this internal info used to compute `error_metric`. We can add some special characters to ignore the result of compute when insert to `engine.state.metrics[name]`.\r\n\r\ncc @zasdfgbnm \n", "before_files": [{"content": "from ignite.metrics.metric import Metric\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    Arguments:\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    Examples:\n        >>> precision = Precision(average=False)\n        >>> recall = Recall(average=False)\n        >>> def Fbeta(r, p, beta):\n        >>>     return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r)).item()\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                metric.attach(engine, name + '[{}]'.format(index))\n        super(MetricsLambda, self).attach(engine, name)\n", "path": "ignite/metrics/metrics_lambda.py"}]}