The syntax error
The syntax error is in assigning **kwargs = . The variable kwargs is a dictionary, and ** unpacks that dictionary. The expression **kwargs = (a = 1) is essentially trying to unpack a dictionary while also assigning that dictionary to another variable assignment.
Keyword arguments
The **kwargs parameter of a function allows you to pass any number of additional keyword arguments. The parameter a=1 is a keyword argument. The kwargs itself is a collection of keyword arguments that you want to "package together".
A quick demonstration:
In [1]: def print_kwargs(**kwargs):
...: for key, value in kwargs.items():
...: print(key, value)
...:
In [2]: print_kwargs(a=1, b=2, c=3)
a 1
b 2
c 3
In [3]: params = dict(a=1, b=2, c=3)
In [4]: print_kwargs(**params)
a 1
b 2
c 3
The actual problem
Looking at the documentation, it looks like the solver is allowed to accept whatever kwargs you pass. In other words, the kwargs aren't passed to your function, func, they're passed to the solver, 'muller' in your case.
The docs suck and the kwargs that the mpmath.calculus.optimization.Muller takes aren't explained at all as far as I can see so I have no idea what it does with its keyword arguments, but the point is that the kwargs aren't being passed to your function as you expected.
Unfortunately you'll need to do a bit more work on your function func if you want it to be a dynamic polynomial which can take arguments for its parameters.
The solution
Here's what you can do:
def function_builder(**params):
def func(x):
return params["a"] * x**2 + 1 # or whatever function
return func
And then you'd do:
>>> params = dict(a=1)
>>> func = function_builder(**params)
>>> mp.findroot(f=func, x0=0.955j, solver='muller')
mpc(real='0.0', imag='1.0')
You can implement function_builder() in such a way as to return a new function object which is only a function of x. Then when you want to find the roots of a particular polynomial, you can call function_builder() with whatever parameters you want and it'll return the function you want to which mp.findroot can then use.
Notes
Here's an example of how you might implement a general quadratic equation builder:
def quadratic_builder(**params):
a, b, c = params["a"], params["b"], params["c"]
def f(x):
return a * x**2 + b * x + c
return f
Of course, for something as specific as a quadratic equation, it'd be better to explicitly call out the keyword arguments:
def quadratic_builder(*, a, b, c):
def f(x):
return a * x**2 + b * x + c
return f
And then you can package together "sets" of coefficients:
coefs_1 = dict(a=1, b=3, c=-5)
coefs_2 = dict(a=-2, b=1, c=0)
coefs_3 = dict(a=-6, b=8, c=3)
f1 = quadratic_builder(**coefs_1)
f2 = quardatic_builder(**coefs_2)
f3 = quardatic_builder(**coefs_3)
Etc.