Repository: sympy/sympy
Pull request: Update solvers to handle binomial.
#### References to other Issues or PRs
Fixes #10993

#### Brief description of what is fixed or changed
Added conditions to expand binomial in solvers
Update expand function for binomial
#### Other comments 
Please suggest changes.

### Release Notes
<!-- BEGIN RELEASE NOTES -->
* solvers
    - Fix solvers to handle binomials
* functions
    - Update expand function for binomials.
<!-- END RELEASE NOTES -->

Problem statement:
Solving equations with binomial coefficients should expand them first
When trying to solve an equation with a binomial coefficient with a symbol, the solver fails:

``` python
>>> solve(Eq(binomial(x, 3), 1000))
```

``` pytb
Traceback (most recent call last):
  File "<ipython-input-7-e56e9952e4b8>", line 1, in <module>
    solve(Eq(binomial(x, 3), 1000))
  File "sympy/solvers/solvers.py", line 1053, in solve
    solution = _solve(f[0], *symbols, **flags)
  File "sympy/solvers/solvers.py", line 1619, in _solve
    raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
NotImplementedError: 
No algorithms are implemented to solve equation binomial(x, 3) - 1000
```

But when expanding the binomial coefficient first, the solver succeeds:

``` python
>>> solve(Eq(binomial(x, 3).expand(func=True), 1000))[2].n()
19.1895499623678
```

Shouldn't the solver try to expand the binomial before failing?

Hints from issue discussion:
I think it is expected because input for `solve` is : 
        - a single Expr or Poly that must be zero,
        - an Equality
        - a Relational expression or boolean
        - iterable of one or more of the above

and `binomial` is a function.

But `binomial` is nothing more than a polynomial, in fact. Shouldn't `solve` recognize it, and expand it instead of raising? That sounds easy enough...

I think this makes sense. Could be worth noting that the current solution to the expanded equation is 
![image](https://user-images.githubusercontent.com/8114497/62460556-9a11cc80-b782-11e9-83e0-7e1b90c0c1a2.png)

Maybe one should add a list of functions that can be rewritten as polynomials and do that for instances of functions that are not solvable otherwise? (It turns out that there is no `_eval_rewrite_as_polynomial` for `binomial`, so that must be added, probably just `return self._eval_expand_func()`.)

Edit: something similar could be done for `solveset` as well.
i want to work on this issue can anyone give me some input since i am new to this community
@sylee957 @asmeurer I would like to take up this issue if no fix has been made for it.

Commit message: Add test.

Patch to review:
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py
index 54023e468260..bf4e42c3ac87 100644
--- a/sympy/solvers/solvers.py
+++ b/sympy/solvers/solvers.py
@@ -14,7 +14,7 @@
 
 from __future__ import print_function, division
 
-from sympy import divisors
+from sympy import divisors, binomial, expand_func
 from sympy.core.compatibility import (iterable, is_sequence, ordered,
     default_sort_key)
 from sympy.core.sympify import sympify
@@ -1027,6 +1027,11 @@ def _sympified_list(w):
                     bare_f = False
                 f[i: i + 1] = [fr, fi]
 
+    #expand binomial terms
+    for i, fi in enumerate(f):
+        if fi.has(binomial):
+            f[i] = fi.replace(lambda exp: binomial, lambda exp: expand_func(exp))
+
     # real/imag handling -----------------------------
     if any(isinstance(fi, (bool, BooleanAtom)) for fi in f):
         if flags.get('set', False):
diff --git a/sympy/solvers/tests/test_solvers.py b/sympy/solvers/tests/test_solvers.py
index 37301d8109ee..531abeed03e0 100644
--- a/sympy/solvers/tests/test_solvers.py
+++ b/sympy/solvers/tests/test_solvers.py
@@ -1,7 +1,7 @@
 from sympy import (
     Abs, And, Derivative, Dummy, Eq, Float, Function, Gt, I, Integral,
     LambertW, Lt, Matrix, Or, Poly, Q, Rational, S, Symbol, Ne,
-    Wild, acos, asin, atan, atanh, cos, cosh, diff, erf, erfinv, erfc,
+    Wild, acos, asin, atan, atanh, binomial, cos, cosh, diff, erf, erfinv, erfc,
     erfcinv, exp, im, log, pi, re, sec, sin,
     sinh, solve, solve_linear, sqrt, sstr, symbols, sympify, tan, tanh,
     root, atan2, arg, Mul, SparseMatrix, ask, Tuple, nsolve, oo,
@@ -2137,6 +2137,11 @@ def test_issue_17949():
     assert solve(exp(+x-x**2), x) == []
     assert solve(exp(-x-x**2), x) == []
 
+def test_issue_10993():
+    assert solve(Eq(binomial(x, 2), 3)) == [-2, 3]
+    assert solve(Eq(pow(x,2) + binomial(x, 3), x)) == [-4, 0, 1]
+    assert solve(Eq(binomial(x,2),0)) == [0, 1]
+
 
 def test_issue_11553():
     eq1 = x + y + 1


Code review comments:
diff_hunk: @@ -1027,6 +1027,11 @@ def _sympified_list(w):
                     bare_f = False
                 f[i: i + 1] = [fr, fi]
 
+    #expand binomial terms
+    for i, fi in enumerate(f):
+        if fi.has(binomial):
+            f[i] = fi.replace(lambda exp: binomial, lambda exp: expand_func(exp))
path: sympy/solvers/solvers.py
text: @user1:
The filter function here will still match non-binomial expressions.

@author:
I will correct it right away.


@user1:
How about:
```python
expand_binomial = lambda f: f.replace(binomial, lambda n, k: expand_func(binomial(n, k)))
f = [expand_binomial(fi) for fi in f]
```

@author:
This one looks more efficient, I will make the changes.

@author:
I earlier thought that binomial expansion should be done in the previous loop as hyperbolic functions are checked and rewritten inside it.

@author:
please review the changes.