I am trying to solve the following problem in matlab but facing some difficulty.
Min t
s.t.
t>= 0.0538λ_2 - 0.7071λ_1
t>= λ_1 - 0.3827λ_2
where 0<=λ_j<=1 for j=1,2
This is what I have so far:
f=[0;0;1]
A=[-0.7071 0.0538 -1;
1 -0.3827 -1]
B=[0;0]
ub=zeros(2,1)
lb=zeros(2,1)
linprog(f,A,B,[],[],lb,ub);
This problem is taken from a research paper and in that the author solved the above problem and found optimal value of t=−0.12698. I am not getting the correct answer with my implementation. Can someone help me please. Also how can I specify in linprog() that I want to use the simplex method.
This should give you the correct result:
f=[1;0;0];
A=[-1 -0.7071 0.0538;
-1 1 -0.3827] ;
B=[0;0] ;
ub=[inf 1 1] ;
lb=[-inf 0 0] ;
options = optimset('Algorithm','simplex');
xres = linprog(f,A,B,[],[],lb,ub,[],options);
Note that linprog expects your input in the format:
min x
s.t. Ax <=b
What I did here, is set the vector x = [t l1 l2], so the first entry in your result vector xres corresponds with t. You can set the algorithm using the optimset function.
Also, you set lower and upper bounds for 2 of the 3 variables only, so matlab gave me some warnings in that regard. To be on the safe side, it is usually best to set 'dummy' limits for the unrestricted variables (i.e. here I set the upper limit of t to inf, and the lower limit to -inf). That way, you make sure the right bounds apply to the right variables.
matrix A is incorrect set.
You need determined what variables where should be.
A=[-0.7071 0.0538 -1;
1 -0.3827 -1]
P.S. Sorry for my English.
Related
First, the data:
orig = reshape([0.0000000000000000 0.3480000000000000 0.7570000000000000 1.3009999999999999 2.8300000000000001 4.7519999999999998 5.2660000000000000 5.8120000000000003 14.3360000000000000 15.3390000000000000 ],[10 1])
change = reshape([0.0000000000000000 0.3480000000000000 0.0000000000000000 0.9530000000000000 1.5290000000000001 1.9219999999999997 0.5140000000000002 0.5460000000000003 0.0000000000000000 9.5270000000000010 ],[10 1])
change = cumsum(change)
orig is a vector of seconds elapsed. change is a vector derived by taking differences between (some) elements of orig. The cumulative sum of change has some elements actually equal to the corresponding element in orig.
However, due to precision issues:
diff = orig - change
gives
diff =
0
0
0.409
0
0
0
0
0
8.524
-1.77635683940025e-15
It seems that if I run the following command:
diff(abs(diff) <= eps(orig)) = 0
then this sets entries which should be zero, but are not due to precision issues, to be zero.
My question is, is this the correct way to do it? Why is the comparison <= instead of <? Should the statement be:
diff(abs(diff) < k*eps(orig)) = 0
for some k > 1 to give some tolerance? If so, how would one pick k?
In case it is necessary to know how change is derived from orig, the following alternate example also shows this behaviour:
orig = reshape([0.0000000000000000 0.3480000000000000 0.7570000000000000 1.3009999999999999 2.8300000000000001 4.7519999999999998 5.2660000000000000 5.8120000000000003 14.3360000000000000 15.3390000000000000 ],[10 1])
change = orig - [0; orig(1:end-1)]
change = cumsum(change)
diff = orig - change
The following statement will be true only if the "almost zero" happens because 1 bit is offseted.
abs(diff) <= eps(orig)
1 bit is a ridiculously high precision to ask, a precision that most likely you can not achieve. Generally, you need to define your treshold yourself, such as
abs(diff) <= 1e-12
You also ask how to choose this value. Answer: there is no way we can tell you that. Its algorithm, application, unit, computer, [...] specific.
You are computing distance between particles? Maybe you need a smaller tolerance. You are doing economic profit calculus? 1e-12 is then a decimal you won't get in cash, for sure. Use 1e-4 instead. Or are you using an algorithm that does numerical approximations? Then you need a higher tolerance. How much tolerance you are OK with is, and will always be, a user choice.
Note: you need to be aware of the types you are using to set this minimum threshold right. MATLAB uses double as default, but if you are using other types, them this threshold is too strict. As an alternative, you can use
abs(diff) <= 100*eps(class(diff))
If your data type is not fixed/known.
I am doing a project about image processing, and I need to solve the following set of equations:
Nx+Nz*( z(x+1,y)-z(x,y) )=0
Ny+Nz*( z(x+1,y)-z(x,y) )=0
and equations of the boundary (bottom and right side of the image):
Nx+Nz*( z(x,y)-z(x-1,y) )=0
Ny+Nz*( z(x,y)-z(x,y-1) )=0
where Nx,Ny,Nz are the surface normal vectors at the corresponding coordinates and are already determined. Now the problem is that since (x,y) are the coordinates on an image, which typically has a size of say x=300 and y=200. So there are 300x200=60000 unknowns. I rewrite the equations in the form of Mz=b, where M has a size of 120,000x60000, and both z and b are vectors of length 60000. When I solve it using the function in python scipy.linalg.lstsq, I run into memory errors.
I notice that M is very sparse as it only has two non-zero entries of either 1 or -1 in each row. However, I don't know how I can utilize it to solve the problem. Any ideas how I can solve it more efficiently in matlab or python?
In python I find a library that has the lsmr method (as mentioned by someone in the comment). Other than using this algorithm to solve the equation Mx=b, I want to know if I need to store M and B in sparse format as well. Now I just create a very large array with all entries zero in the beginning, then I use a for loop to loop over each pixel and change the corresponding entries to 1 or -1. Then I apply lsmr to solve Mx=b directly. Does it help if I construct the matrix M and b in any one of the sparse format? Right now most of the time spent is in solving Mx=b. Construct the array M,b and doing all previous tasks take negligible time compared to solving Mx=b.
thanks
edit: this is the python code I use to generate matrix M and b. They should be 'correct', but not sure if there are other better ways of rewriting the system of linear equations.
eq_no = 0
for pix in range(total_pix):
row, col = y[pix], x[pix]
if index_array[row,col] >= 0: # confirm (x,y) is inside boundary
# check x-direction
if index_array[row,col+1] >= 0: # (x+1,y) is inside boundary
M[eq_no,pix] = -1
M[eq_no,pix+1] = 1
b[eq_no,0] = -normal_array[row,col,0]/normal_array[row,col,2]
eq_no += 1
# check y-direction
next_pix = index_array[row+1,col]
if next_pix >= 0:
M[eq_no , pix] = -1
M[eq_no , next_pix] = 1
b[eq_no,0] = -normal_array[row,col,1]/normal_array[row,col,2]
eq_no += 1
I trying to minimize function handle with respect to vector of parameters beta0. My function uses built-in mvncdf function which uses positive definite covariance matrix. This matrix is counted from part of vector of parameters. Also there is constraint for absolute value of some parameters to be less than one.
I set constraints to fmincon in two ways: upper and lower bounds to required values and use following nonlinear constraint:
function [c,ceq] = pos_def(beta0)
rho_12 = beta0(end-2,1);
rho_13 = beta0(end-1,1);
rho_23 = beta0(end,1);
sigma111=[1 rho_12 rho_13; rho_12 1 rho_23; rho_13 rho_23 1];
sigma110=[1 rho_12 -rho_13; rho_12 1 -rho_23; -rho_13 -rho_23 1];
sigma101=[1 -rho_12 rho_13; -rho_12 1 -rho_23; rho_13 -rho_23 1];
sigma100=[1 -rho_12 -rho_13; -rho_12 1 rho_23; -rho_13 rho_23 1];
eig111 = eig(sigma111);
eig110 = eig(sigma110);
eig101 = eig(sigma101);
eig100 = eig(sigma100);
c = vertcat(-eig111,-eig110,-eig101,-eig100);
As all matrices are square and symmentric by constraction, as proxy to positive difiniteness I use signs of eigenvalues.
The optimization problem looks like:
opts = optimset ('Display','iter','TolX',1e-15,'TolFun',1e-15,...
'Algorithm','interior-point','MaxIter',100000,'MaxFunEvals',1000000);
xc3_3=fmincon(model, beta,[],[],[],[],lb,ub,#pos_def, opts)
But during estimation fmincon aborts with error
Error using mvncdf (line 193) SIGMA must be a square, symmetric, positive definite matrix.
Under debuging mode I can see that after two iterations of evaluation Matlab tries to estimate beta0 which does not sutisfy my nonlinear constraints,
beta0 =
-46.9208
33.2916
-2.1797
-46.4251
3.8337
-0.3066
6.1213
-20.9480
-1.7760
-0.1807
1.3950
4.5348
-0.9838
0.2600
-6.9887
-24.6157
-0.0112
-0.9923
-0.9284
0.7664
0.3062
And constraint c < 0 does not satisfied:
c =
0.3646
-1.2998
-2.0648
0.3646
-1.2998
-2.0648
0.3646
-1.2998
-2.0648
0.3646
-1.2998
-2.0648
I do not understand why this optimization tool trying to find solution in the prohibited area and how to avoid this problem. Or how to set constrains on positive definiteness in the linear way.
The optimizer is just evaluating points to see if they are feasible directions to move in or not. Within your model you should tell it that a particular direction is not a good one. The pseudo-code would look something like
GetEigvalues
if (positive definite) then
Do what you really want to happen
else
Return a large number
end
or alternatively
try
Do what you really want to happen
catch
Return a large number
end
I would like to maximize this function in MatLab - http://goo.gl/C6pYP
maximize | function | 3x+6y+9z
domain | 12546975x+525x^2+25314000y+6000y^2+47891250z+33750z^2<=4000000000 | for | x y z
But variables x, y and z have to be nonnegative integers only.
Any ideas how to achieve it in MatLab?
The fact that you want integers makes this problem very difficult to solve (i.e. unsolvable in a reasonable time).
You will have to use some general optimizer and just try many starting conditions by brute force. You will not be guaranteed to find a global maximum. See Matlab's optimization package for further possible optimizers.
You have to formulate the problem as an ILP ( integer linear program). To solve an ILP, you need to make few changes to the input to matlab LP solver . You can also get the solution from the LP solver and then round the solution to integer. The solution may not be optimal but will be close.
You can also use the mixed-integer liner programing solver at file exchange site that in turn uses the LP solver. For binary variables you can use the matlab binary integer programing solver.
Well, fortunately the problem size is tiny so we can just brute force it.
First get some upper limits, here is how to do it for x:
xmax= 0;
while 12546975*xmax+525*xmax^2<=4000000000
xmax=xmax+1;
end
This gives us upper limits for all three variables. Now we can see that the product of these limits is not a lot so we can just try all solutions.
bestval = 0;
for x = 0:xmax
for y = 0:ymax
for z = 0:zmax
val = 3*x+6*y+9*z;
if val> bestval && 12546975*x+525*x^2+25314000*y+6000*y^2+47891250*z+33750*z^2<=4000000000
bestval = val;
best = [x y z];
end
end
end
end
best, bestval
This is probably not the most efficient way to do it, but it should be very easy to read.
The max of y and z(152,79) is not very high,so we can just check one by one to find the solution quickly(just 0.040252 seconds in my notebook computer).
My matlab code:
function [MAX,x_star,y_star,z_star]=stackoverflow1
%maximize 3x+6y+9z
% s.t. 12546975x+525x^2+25314000y+6000y^2+47891250z+33750z^2<=4000000000
MAX=0;
y_max=solver(6000,25314000,-4000000000);
z_max=solver(33750,47891250,-4000000000);
for y=0:floor(y_max)
for z=0:floor(z_max)
x=solver(525,12546975,+25314000*y+6000*y^2+47891250*z+33750*z^2-4000000000);
x=floor(x);
if isnan(x) || x<0
break;
end
if 3*x+6*y+9*z>MAX
MAX=3*x+6*y+9*z;
x_star=x;
y_star=y;
z_star=z;
end
end
end
end
function val=solver(a,b,c)
% this function solve equation a*x^2+b*x+c=0.
% this equation should have two answers,this function returns the bigger one only.
if b*b-4*a*c>=0
val=(-b+sqrt(b*b-4*a*c))/(2*a);
else
val=nan; % have no real number answer.
end
end
The solution is:
MAX =
945
x_star =
287
y_star =
14
z_star =
0
In order to find best fit (thru polyfit), i am getting negative p value but matlab is not accepting it (Subscript indices must either be real positive integers or logicals.). Is there any way that I can use it ? I can't think of alternative method. I'll always get negative values.
EDIT:
I am trying to flattening baseline of a curve, for that. I am running for loop to have fit from 1 to 3 order. And then I am using smallest normr s value to to find the best fit and then subtract it from the whole curve to get baseline straight. I tried with few curves it works well but not with all of the data because of above describes issue.
part of the code I am working on:
for i=1:3
[p,s]=polyfit(x,y,i);
a=s.normr;
b(i,1)=p(1);
normr(i,1)=a;
ind=find(b==min(b));
mn=b(ind,1);
Yflat=y-mn(1)*(x-mean(x));
ca{2,2}=Yflat;
clear a b normr p s rte ind ind2 Yflat
end
When I translate an image into negative coordinates,
I usually record an offset e.g.
offset = [ -5, -8.5 ]
and save the intensity values in matrix begin with (1, 1) as usual,
But when comes to calculation, let the coordinates array add up with the offset
e.g. [ actualX, actualY ] = [ x, y ] + offset ;
It may need extra efforts, but it works.
Good Luck!
The code below (your code from the comments + initialization of x, y) executes. What is the problem?
x = 1:50;
y = randn(size(x));
for i=1:3
[p,s]=polyfit(x,y,i);
a=s.normr;
b(i,1)=p(1);
normr(i,1)=a;
ind=find(b==min(b));
mn=b(ind,1);
Yflat=y-mn(1)*(x-mean(x));
ca{2,2}=Yflat;
end