Repository: pytorch/ignite

Issue:
Issue with metric arithmetics
I'm trying to define my metric as 
```python
from ignite.metrics import Accuracy

accuracy = Accuracy()
error_metric = 1.0 - accuracy
```
and I got the following error:
```
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-70-c4c69e70a6d5> in <module>()
      2 
      3 accuracy = Accuracy()
----> 4 error_metric = 1.0 - accuracy

TypeError: unsupported operand type(s) for -: 'float' and 'Accuracy'
```
But I can define 
```python
from ignite.metrics import Accuracy

accuracy = Accuracy()
error_metric = (accuracy - 1.0) * -1.0
```

cc @zasdfgbnm 
Issue with metric arithmetics
I'm trying to define my metric as 
```python
from ignite.metrics import Accuracy

accuracy = Accuracy()
error_metric = 1.0 - accuracy
```
and I got the following error:
```
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-70-c4c69e70a6d5> in <module>()
      2 
      3 accuracy = Accuracy()
----> 4 error_metric = 1.0 - accuracy

TypeError: unsupported operand type(s) for -: 'float' and 'Accuracy'
```
But I can define 
```python
from ignite.metrics import Accuracy

accuracy = Accuracy()
error_metric = (accuracy - 1.0) * -1.0
```

cc @zasdfgbnm 


Discussion:

Resolving patch:
diff --git a/ignite/metrics/metric.py b/ignite/metrics/metric.py
--- a/ignite/metrics/metric.py
+++ b/ignite/metrics/metric.py
@@ -78,18 +78,34 @@ def __add__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x + y, self, other)
 
+    def __radd__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x + y, other, self)
+
     def __sub__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x - y, self, other)
 
+    def __rsub__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x - y, other, self)
+
     def __mul__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x * y, self, other)
 
+    def __rmul__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x * y, other, self)
+
     def __pow__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x ** y, self, other)
 
+    def __rpow__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x ** y, other, self)
+
     def __mod__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x % y, self, other)
@@ -98,10 +114,18 @@ def __div__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x.__div__(y), self, other)
 
+    def __rdiv__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x.__div__(y), other, self)
+
     def __truediv__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x.__truediv__(y), self, other)
 
+    def __rtruediv__(self, other):
+        from ignite.metrics import MetricsLambda
+        return MetricsLambda(lambda x, y: x.__truediv__(y), other, self)
+
     def __floordiv__(self, other):
         from ignite.metrics import MetricsLambda
         return MetricsLambda(lambda x, y: x // y, self, other)


Test patch:
diff --git a/tests/ignite/metrics/test_metric.py b/tests/ignite/metrics/test_metric.py
--- a/tests/ignite/metrics/test_metric.py
+++ b/tests/ignite/metrics/test_metric.py
@@ -90,7 +90,6 @@ def update(self, output):
             self.list_ = output
 
         def compute(self):
-            print(self.index)
             return self.list_[self.index]
 
     m0 = ListGatherMetric(0)
@@ -110,6 +109,10 @@ def compute(self):
     m2.update([1, 10, 100])
     assert m2_plus_2.compute() == 102
 
+    m2_plus_2 = 2 + m2
+    m2.update([1, 10, 100])
+    assert m2_plus_2.compute() == 102
+
     # __sub__
     m0_minus_m1 = m0 - m1
     m0.update([1, 10, 100])
@@ -123,6 +126,10 @@ def compute(self):
     m2.update([1, 10, 100])
     assert m2_minus_2.compute() == 98
 
+    m2_minus_2 = 2 - m2
+    m2.update([1, 10, 100])
+    assert m2_minus_2.compute() == -98
+
     # __mul__
     m0_times_m1 = m0 * m1
     m0.update([1, 10, 100])
@@ -136,6 +143,10 @@ def compute(self):
     m2.update([1, 10, 100])
     assert m2_times_2.compute() == 200
 
+    m2_times_2 = 2 * m2
+    m2.update([1, 10, 100])
+    assert m2_times_2.compute() == 200
+
     # __pow__
     m0_pow_m1 = m0 ** m1
     m0.update([1, 10, 100])
@@ -149,6 +160,10 @@ def compute(self):
     m2.update([1, 10, 100])
     assert m2_pow_2.compute() == 10000
 
+    m2_pow_2 = 0.99 ** m2
+    m2.update([1, 10, 100])
+    assert m2_pow_2.compute() == 0.3660323412732292
+
     # __mod__
     m0_mod_m1 = m0 % m1
     m0.update([1, 10, 100])
@@ -176,6 +191,10 @@ def compute(self):
         m2.update([1, 10, 100])
         assert m2_div_2.compute() == 50
 
+        m2_div_2 = 200 / m2
+        m2.update([1, 10, 100])
+        assert m2_div_2.compute() == 2
+
     # __truediv__
     m0_truediv_m1 = m0.__truediv__(m1)
     m0.update([1, 10, 100])
@@ -189,6 +208,10 @@ def compute(self):
     m2.update([1, 10, 100])
     assert m2_truediv_2.compute() == approx(50.0)
 
+    m2_truediv_2 = m2.__rtruediv__(200)
+    m2.update([1, 10, 100])
+    assert m2_truediv_2.compute() == approx(2.0)
+
     # __floordiv__
     m0_floordiv_m1 = m0 // m1
     m0.update([1, 10, 100])