This is not a programming question, but here goes: integral equations are quite often numerically badly conditioned.
Indeed, in your case,
u, s, vh = linalg.svd(A)
print(s.max()/s.min())
# -> 4.03758642411e+16
This is the condition number, and it's huge. The matrix A
is nearly singular, so there will be a large error in the solution.
Googling for "Tikhonov regularization" should get you started on how people work around issues like this. Solving integral equations is a mature field in mathematics, so googling should help you a lot here.
A quick regularization is replacing linalg.inv(A)
with
linalg.pinv(A, 1e-8)
This gives something more cosine looking. The magic value 1e-8
depends on the integral kernel, but when things are about rounding error, good values to try are around sqrt(finfo(float).eps)
which is saying that you trust half of the ~15 digits that floating point numbers have.
Also, a change of variables may be a better idea than truncating the range of u
to [0, 5]
. The numerical issue in your case is possibly related to the exponentially decreasing weight factor, so getting rid of that via a change of variables may also make the condition number better.