I suspect that the error gets raised because your function returns a symbolic expression, and scipy doesn't know what to do with it. As you can see from the error, the result of the function contains additions, multiplications, radical... You could try to write return func.n(), but I don't know if that's going to work: in fact, your function is so slow to evaluate that I suggest to completely switch to a purely numerical approach.
Scipy's minimize (and every other scipy function) requires numerical data to work properly. Hence, we need to rewrite your symbolic expression as a numerical function which will return a numeric value. This, in turn, will results in an faster execution :)
Let's consider your expression:
N = Normal("N", args[0], args[1])
y = Symbol("y", real = True)
samples = list(sample_iter(N, numsamples=200))
sampleSum = sum(samples)
func = simplify((Sum(sum([simplify(binomial(20,y)*(1/(1+exp(-sample)))**y*(exp(-sample)/(1+exp(-sample)))**(20-y)*density(N)(sample))/sampleSum for sample in samples]), (y, 0, 10)).doit() - 0.8)**2)
sample can be generated with numpy.random.normal
binomial(20,y) can be lambdified (convert to a numerical function).
density(N)(sample) can be replaced with norm.pdf from scipy.stats.
- the two sums can be done without the need of symbolic objects.
from sympy import Symbol, binomial, lambdify
from scipy.stats import norm
from scipy.optimize import minimize
import numpy as np
y = Symbol("y", real = True)
# create a numerical function to compute the binomial
binomial_f = lambdify([y], binomial(20, y))
def inner_sum(y, args):
samples = np.random.normal(args[0], args[1], 200)
sampleSum = sum(samples)
return sum([(binomial_f(y) * (1/(1+np.exp(-sample)))**y*(np.exp(-sample)/(1+np.exp(-sample)))**(20-y)*norm.pdf(sample, args[0], args[1])) / sampleSum for sample in samples])
def outer_sum(args):
val = (sum([inner_sum(y, args) for y in range(11)]) - 0.8)**2
print(*args, val)
return val
results = minimize(outer_sum, [1,1], method='BFGS', options={"disp": True, "return_all": True})
print(results)
# Warning: Desired error not necessarily achieved due to precision loss.
# Current function value: 0.570869
# Iterations: 1
# Function evaluations: 68
# Gradient evaluations: 19
# allvecs: [array([1., 1.]), array([1.00000958, 0.99998663])]
# fun: 0.5708685806309425
# hess_inv: array([[1.35282892e-03, 6.12645895e-02],
# [6.12645895e-02, 2.77444541e+00]])
# jac: array([129387.86052179, 454897.50102044])
# message: 'Desired error not necessarily achieved due to precision loss.'
# nfev: 68
# nit: 1
# njev: 19
# status: 2
# success: False
# x: array([1.00000958, 0.99998663])