| American Citizen on Sat, 06 Dec 2025 01:42:58 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| trying to set up Gauss-Newton method for fitting a power law curve |
Hello:The count of triads of squares = n (a given number) seems to follow a power law of n = 5.9 * count ^ 1.92 more or less.
Here is my attempt at implementing that algorithm, but it is running very slowly for 80,942 elements [ count, n ] vector.
Is this about right? Randall/* Function to calculate the residuals based on current parameters a and b */
residuals(a, b, data) = {
my(res, n, count, i);
res = 0; \\ Initialize the residual sum
for (i = 1, length(data),
n = data[i][2]; \\ Get n
count = data[i][1]; \\ Get count
res += (count - a * n^b)^2; \\ Calculate the squared residual
);
return(res);
}
/* Jacobian matrix calculation */
jacobian(a, b, data) = {
my(J, n, count, i);
J = matrix(length(data), 2); \\ Initialize Jacobian matrix
for (i = 1, length(data),
n = data[i][2];
count = data[i][1];
J[i, 1] = -n^b; \\ Derivative with respect to a
J[i, 2] = -a * n^b * log(n); \\ Derivative with respect to b
);
return(J);
}
/* Gauss-Newton method for fitting */
gauss_newton(data, a0, b0, max_iter, tol) = {
my(a, b, iter, delta, J, r);
a = a0; \\ Initialize a
b = b0; \\ Initialize b
for (iter = 1, max_iter,
print("at iteration: ", iter);
r = vector(length(data), i, data[i][2] - a * data[i][1]^b)~; \\
Residuals
J = jacobian(a, b, data); \\ Compute Jacobian
\\ Solve the normal equations J' * J * [delta_a, delta_b] = -J' * r
my(JtJ, Jtr, scaled);
JtJ = mattranspose(J) * J; \\ Compute J' * J
Jtr = mattranspose(J) * r; \\ Compute J' * r
scaled = 100000000; \\ initial guess
delta = scaled * matsolve(JtJ, -Jtr); \\ Solve for delta
print("delta : ",delta);
\\ Update parameters
a += delta[1]; \\ Update a
b += delta[2]; \\ Update b
\\ Optionally print current estimates
print("Iteration: ", iter, " a: ", a, " b: ", b);
\\ Check for convergence (could set a tolerance value)
if (sqrt(delta[1]^2 + delta[2]^2) < tol, break);
);
return([a, b]); \\ Return the optimized parameters
}
resolve(file,tol) = {
my(data, sz, a0, b0, max_iter, params);
data = readvec(file);
sz = matsize(data)[2];
print("Input size: ", sz);
a0 = 5.9791; \\ Initial guess for a
b0 = 1.9288; \\ Initial guess for b
max_iter = 100; \\ Maximum number of iterations
\\ Run the Gauss-Newton fitting
params = gauss_newton(data, a0, b0, max_iter, tol);
print("Optimized parameters: ", params);
}