Samuel Reid
Samuel Reid

Reputation: 145

Making a function in terms of a sum from 1 to n in Matlab

I'm trying to get Matlab to take this as a function of x_1 through x_n and y_1 through y_n, where k_i and r_i are all constants.

$$ \sum_{i=2}^{n} ( k_{i-1}*( \sqrt ( (x_i - x_{i-1})^2 + (y_{i}-y_{i-1})^2 ) -r_{i-1})^2$$

So far my idea was to take n from the user and make two 1×n vectors called x and y, and for the x_i just pull out x(i). But I don't know how to make an arbitrary sum in MATLAB.

I also need to get the gradient of this function, which I don't know how to do either. I was thinking maybe I could make a loop and add that to the function each time, but MATLAB doesn't like that.

Upvotes: 2

Views: 2396

Answers (4)

aardvarkk
aardvarkk

Reputation: 15996

I don't believe a loop is necessary for this calculation. MATLAB excels at vectorized operations, so would something like this work for you?

l = 10; % how large these vectors are
k = rand(l,1); % random junk values to work with
r = rand(l,1);
x = rand(l,1);
y = rand(l,1);
vals = k(1:end-1) .* (sqrt(diff(x).^2 + diff(y).^2) - r(1:end-1)).^2;
sum(vals)

EDIT: Thanks to @Amro for correcting the formula and simplifying it with diff.

Upvotes: 3

horchler
horchler

Reputation: 18484

You can solve for the gradient symbolically with:

n = 10;
k = sym('k',[1 n]); % Create n variables k1, k2, ..., kn
x = sym('x',[1 n]); % Create n variables x1, x2, ..., xn
y = sym('y',[1 n]); % Create n variables y1, y2, ..., yn
r = sym('r',[1 n]); % Create n variables r1, r2, ..., rn
% Symbolically sum equation
s = sum((k(1:end-1).*sqrt((x(2:end)-x(1:end-1)).^2+(y(2:end)-y(1:end-1)).^2)-r(1:end-1)).^2)
grad_x = gradient(s,x) % Gradient with respect to x vector
grad_y = gradient(s,y) % Gradient with respect to y vector

The symbolic sum and gradients can be evaluated and converted to floating point with:

% n random data values for k, x, y, and r
K = rand(1,n);
X = rand(1,n);
Y = rand(1,n);
R = rand(1,n);
% Substitute in data for symbolic variables
S = double(subs(s,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_X = double(subs(grad_x,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_Y = double(subs(grad_y,{[k,x,y,r]},{[K,X,Y,R]}))

The gradient function is the one overloaded for symbolic variables (type help sym/gradient) or see the more detailed documentation online).

Upvotes: 1

Dmitry Galchinsky
Dmitry Galchinsky

Reputation: 2201

Vectorized solution is something like (I wonder why do you use sqrt().^2):

is = 2:n;
result = sum( k(is - 1) .* abs((x(is) - x(is-1)).^2 + (y(is) - y(is-1)).^2 - r(is-1)));

You can either compute gradient symbolically or rewrite this code as a function and make a standard +-eps calculation. If you need a gradient to run optimization (you code looks like a fitness function) you could use algorithms that calculate them themselves, for example, fminsearch can do this

Upvotes: 0

s.bandara
s.bandara

Reputation: 5664

Yes, you could indeed do this with a loop, considering that x, y, k, and r are already defined.

n = length(x);
s = 0;
for j = 2 : n
    s = s + k(j-1) * (sqrt((x(j) - x(j-1)).^2 + (y(j) - y(j-1)).^2) - r(j-1)).^2
end

You should derive the gradient analytically and then plug in numbers. It should not be too hard to expand these terms and then find derivatives of the resulting polynomial.

Upvotes: 0

Related Questions