Repository: sympy/sympy

Issue:
Information Theory Measures
It would be really good for the `stats` module to have functions to calculate self-information, entropy, Kullback-Leibler divergence, etc. Currently, there are a lot of problems related to `H` in stats. Some of them are - 
``` python
>>> from sympy import *
>>> from sympy.stats import *
>>> n,p=symbols('n p')
>>> B=Binomial('B', n, p)
>>> H(B)
AttributeError: 'Density' object has no attribute 'values'

>>> m, s = symbols('m s')
>>> N=Normal("N", m, s)
>>> H(N)
Hangs
```
[Introduction to Information Theory](https://colab.research.google.com/github/d2l-ai/d2l-en-colab/blob/master/chapter_appendix-mathematics-for-deep-learning/information-theory.ipynb)


Discussion:

Patch:
diff --git a/sympy/stats/rv_interface.py b/sympy/stats/rv_interface.py
index 073f7f2882..85dd36925c 100644
--- a/sympy/stats/rv_interface.py
+++ b/sympy/stats/rv_interface.py
@@ -133,8 +133,8 @@ def entropy(expr, condition=None, **kwargs):
     """
     pdf = density(expr, condition, **kwargs)
     base = kwargs.get('b', exp(1))
-    if hasattr(pdf, 'dict'):
-            return sum([-prob*log(prob, base) for prob in pdf.dict.values()])
+    if isinstance(pdf, dict):
+            return sum([-prob*log(prob, base) for prob in pdf.values()])
     return expectation(-log(pdf(expr), base))
 
 def covariance(X, Y, condition=None, **kwargs):


Test patch:
diff --git a/sympy/stats/tests/test_rv.py b/sympy/stats/tests/test_rv.py
index 086e5f78df..1016f2f184 100644
--- a/sympy/stats/tests/test_rv.py
+++ b/sympy/stats/tests/test_rv.py
@@ -1,4 +1,4 @@
-from sympy import (S, Symbol, Interval, exp, Or,
+from sympy import (S, Symbol, Interval, binomial, nan, exp, Or,
         symbols, Eq, cos, And, Tuple, integrate, oo, sin, Sum, Basic, Indexed,
         DiracDelta, Lambda, log, pi, FallingFactorial, Rational, Matrix)
 from sympy.stats import (Die, Normal, Exponential, FiniteRV, P, E, H, variance,
@@ -12,6 +12,8 @@
 from sympy.external import import_module
 from sympy.core.numbers import comp
 from sympy.stats.frv_types import BernoulliDistribution
+from sympy.core.symbol import Dummy
+from sympy.functions.elementary.piecewise import Piecewise
 
 def test_where():
     X, Y = Die('X'), Die('Y')
@@ -385,3 +387,10 @@ def test_issue_6810():
     assert P(Eq(Y, 0)) == 0
     assert P(Or(X > 2, X < 3)) == 1
     assert P(And(X > 3, X > 2)) == S(1)/2
+
+def test_issue_20286():
+    n, p = symbols('n p')
+    B = Binomial('B', n, p)
+    k = Dummy('k', integer = True)
+    eq = Sum(Piecewise((-p**k*(1 - p)**(-k + n)*log(p**k*(1 - p)**(-k + n)*binomial(n, k))*binomial(n, k), (k >= 0) & (k <= n)), (nan, True)), (k, 0, n))
+    assert eq.dummy_eq(H(B))