Here is the objective function I am trying to write in CVXPY:
where matrix F (nxn) is my variable, A and W are known matrices and lambda is a tuning parameter (that I set to 1).
I can't figure out how to use CVXPY functions like sum or cumsum for the second part of the equation, so I used loops:
F = cp.Variable((n,n))
temp_1 = 0
temp_2 = 0
for i in range(n):
for j in range(n):
temp_1 += pow(A[i][j]-F[i][j],2)
for i in range(n):
for i_prim in range(n):
for j in range(n):
for j_prim in range(n):
temp_2+=W[i][i_prim] * W[j][j_prim] * pow(F[i][j]-F[i_prim][j_prim],2)
cost = 1/pow(n,2) * temp_1 + 1/pow(n,4) * temp_2
objective = cp.Minimize(cost)
prob = cp.Problem(objective)
prob.solve()
However, this seems to create an infinite loop and crashes my program.
TLDR: Can I use premade functions like sum or cumsum for the second part of the equation? If yes, how?
Thanks in advance!
Related
I am interested in writing some matrix elements as functions which can take value as per my convenience and then the required matrix operations can be applied on top of that. More precisely, I am trying to integrate over x, the trace of a matrix which has matrix elements as functions of x (which are unknown analytically as they come through products of matrices dependent on x) .
When I try to write the matrix elements as functions, then I obviously get the error- Conversion to double from function_handle is not possible. Is there an easy way to write the matrix elements as functions ?
Thanks. Please ask if my question is not clear.
For example, its something like this:-
N_k = 10;
M_sigma = cell(N_k,1);
M_rho = cell(N_k,1);
for ii = 1:N_k
M_sigma {ii}(1,2) = #(sigma) sigma; %this kind of thing is not allowed in matlab
M_sigma {ii}(2,1) = #(sigma) -conj(sigma);
M_sigma {ii}(1,1) = 0;
M_sigma {ii}(2,2) = 0;
end
for ii = 1:N_k
M_rho {ii}(1,2) = #(rho) rho;
M_rho {ii}(2,1) = #(rho) -conj(rho);
M_rho {ii}(1,1) = 0;
M_rho {ii}(2,2) = 0;
end
M_tau = cell(N_k,1);
for ii = 1:N_k
M_tau {ii} = exp(M_sigma{ii})*exp(M_rho{ii});
end
% the following statement is wrong but I want to do something like
%:-write M_tau as a function of sigma and sum(integrate) the trace of M_tau for all values of sigma
integral(#(sigma) M_tau{1}(sigma), {0,1})
I don't think that you would be able to accomplish that with function handles. I think the best way you could do it would be to define a function as follows :
function x = myFunction(rowindex,colindex)
x = x * rowindex + colindex;
end
You would replace this function with your algorithm and then you could iterate over it doing the following:
for a=1:10
for b=1:10
x(a,b)=myFunction(a,b);
end
end
So I am trying to go through a for loop that will increment .1 every time and will do this until the another variable h is less than or equal to zero. Then I am suppose to graph this h variable along another variable x. The code that I wrote looks like this:
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
h(t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
The Error that I keep getting when running this code says "Attempted to access h(0); index must be a positive integer or logical." I don't understand what exactly is going on in order for this to happen. So my question is why is this happening and is there a way I can solve it, Thank you in advance.
You're using t as your loop variable as well as your indexing variable. This doesn't work, because you'll try to access h(0), h(0.1), h(0.2), etc, which doesn't make sense. As the error says, you can only access variables using integers. You could replace your code with the following:
t = 0:0.1:12;
for i = 1:length(t)
% use t(i) instead of t now
end
I will also point out that you don't need to use a for loop to do this. MATLAB is optimised for acting on matrices (and vectors), and will in general run faster on vectorised functions rather than for loops. For instance, your equation for h could be replaced with the following:
O = 20;
v = 200;
g = 32.2;
t = 0:0.1:12;
h = v * t * sin(O) - 0.5 * g * t.^2;
The only difference is that you have to use the element-wise square (.^2) rather than the normal square (^2). This means that MATLAB will square each element of the vector t, rather than multiplying the vector t by itself.
In short:
As the error says, t needs to be an integer or logical.
But your t is t=0:0.1:12, therefore a decimal value.
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
idx_t = 1:numel(t);
h(idx_t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(idx_t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
Look this question's answer for more options: Subscript indices must either be real positive integers or logical error
I'm trying to write a Non-Local Means filter for an assignment. I've written the code in two ways, but the method I'd expect to be quicker is much slower than the other method.
Method 1: (This method is slower)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
w = exp((-abs(I-I(i,j))^2)/(h^2));
Z = sum(sum(w));
w = w/Z;
sumV = w .* I;
NL(i,j) = sum(sum(sumV));
end
toc
end
Method 2: (This method is faster)
for i = 1:size(I,1)
tic
sprintf('%d/%d',i,size(I,1))
for j = 1:size(I,2)
Z = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
Z = Z + w;
end
end
sumV = 0;
for k = 1:size(I,1)
for l = 1:size(I,2)
w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2));
w = w/Z;
sumV = sumV + w * I(k,l);
end
end
NL(i,j) = sumV;
end
toc
end
I really thought that MATLAB would be optimized for Matrix operations. Is there reason it isn't in this code? The difference is pretty large. For a 512x512 image, with h = 0.05, one iteration of the outer loop takes 24-28 seconds for Method 1 and 10-12 seconds for Method 2.
The two methods are not doing the same thing. In Method 2, the term abs(I(i,j)-I(k,l)) in the w= expression is being squared, which is fine because the term is just a single numeric value.
However, in Method 1, the term abs(I-I(i,j)) is actually a matrix (The numeric value I(i,j) is being subtracted from every element in the matrix I, returning a matrix again). So, when this term is squared with the ^ operator, matrix multiplication is happening. My guess, based on Method 2, is that this is not what you intended. If instead, you want to square each element in that matrix, then use the .^ operator, as in abs(I-I(i,j)).^2
Matrix multiplication is a much more computation intensive operation, which is likely why Method 1 takes so much longer.
My guess is that you have not preassigned NL, that both methods are in the same function (or are scripts and you didn't clear NL between function runs). This would have slowed the first method by quite a bit.
Try the following: Create a function for both methods. Run each method once. Then use the profiler to see where each function spends most of its time.
A much faster implementation (Vectorized) could be achieved using im2col:
Create a Vector out of each neighborhood.
Using predefined indices calculate the distance between each patch.
Sum over the values and the weights using sum function.
This method will work with no loop at all.
I want to compute the following infinite sum in Matlab, for a given x and tau:
I tried the following code, given x=0.5 and tau=1:
symsum((8/pi/pi)*sin(n*pi*0.5)*sin(n*pi*0.5)*exp(-n*n*pi*pi)/n/n,1,inf)
But I get this:
(228155022448185*sum((exp(-pi^2*n^2)*((exp(-(pi*n*i)/2)*i)/2 - (exp((pi*n*i)/2)*i)/2)^2)/n^2, n == 1..Inf))/281474976710656
I want an explicit value, assuming the sum converges. What am I doing wrong? It seems like Matlab doesn't compute exp() when returning symsum results. How do I tell Matlab to compute evaluate the exponentials?
Convert to double
double(symsum(...))
Just to show you a different way, one that does not require the symbolic toolbox,
summ = 0;
summP = inf;
n = 1;
while abs(summP-summ) > 1e-16
summP = summ;
summ = summ + sin(n*pi*0.5)*sin(n*pi*0.5)*exp(-n*n*pi*pi)/n/n;
n = n + 1;
end
8/pi/pi * summ
which converges after just 1 iteration (pretty obvious, since exp(-4*6.28..)/n/n is so tiny, and sin(..) is always somewhere in [-1 1]). So given tau==1 and x==0.5, the infinite sum is essentially the value for n==1.
You should first define your variable "n" using syms. Then, you can include this variable in your symsum code.
Here's what I did:
syms n; AA = symsum((8/pi/pi)*sin(n*pi*0.5)*sin(n*pi*0.5)*exp(-n*n*pi*pi)/n/n,n,1,inf); BB = double(AA)
BB = 4.1925e-05
I have a summation objective function (non-linear portfolio optimization) which looks like:
minimize w(i)*w(j)*cv(i,j) for i = 1 to 10 and j = 1 to 10
w is the decision vector
cv is a known 10 by 10 matrix
I have the formulation done for the constraints (a separate .m file for the project constraints) and for the execution of the fmincon (a separate .m file for the lower/upper bounds, initial value, and calling fmincon with the arguments).
I just can't figure out how to do the objective function. I'm used to linear programming in GLPK rather than matlab so I'm not doing so good.
I'm currently got:
ObjectiveFunction.m
function f = obj(w)
cv = [all the constants are in here]
i = 1;
j = 1;
n = 10;
var = 0;
while i <= n
while j<=n
var = var + abs(w(i)*w(j)*cv(i, j));
j = j + 1;
end
i = i + 1;
end
f = var
...but this isn't working.
Any help would be appreciated! Thanks in advance :)
So this is from a class I took a few years ago, but it addresses a very similar problem to your own with respect to use of fminsearch to optimize some values. The problem is essentially that you have a t, y, and you want a continuous exponential function to represent t, y in terms of c1*t.*exp(c2*t). The textbook I lifted the values from is called Numerical Analysis by Timothy Sauer. Unfortunately, I don’t remember the exact problem or chapter, but it’s in there somewhere.
c1 and c2 are found recursively by fminsearch minimizing a residual y - ((c1) * t .* exp((c2) * t)). Try copying and running my code below to get a feel for things:
%% Main code
clear all;
t = [1,2,3,4,5,6,7,8];
y = [8,12.3,15.5,16.8,17.1,15.8,15.2,14];
lambda0=[1 -.5];
lambda=fminunc(#expdecayfun,lambda0, ...
optimset('LargeScale','off','Display','iter','TolX',1.e-6),t,y);
c1=lambda(1);
c2=lambda(2);
fprintf('Using the BFGS method through fminunc, c1 = %e\n',c1);
fprintf('and c2 = %e. Since these values match textbook values for\n', c2);
fprintf('c1 and c2, I will stop here.\n');
%% Index of functions:
% expdecayfun
function res=expdecayfun(lambda,t,y) c1=lambda(1);
c2=lambda(2);
r=y-((c1)*t.*exp((c2)*t));
res=norm(r);
Hope this helps!