I'm trying to solve a cone program in Matlab by calling MOSEK while varying the bound on one of the constraints.
I would like to do so in parallel to take advantage of all the cores that I have. Here is a modified example to illustrate my point.
testBounds=[0.1, 0.15, 0.2, 0.25, 0.3];
clear prob;
[r, res] = mosekopt('symbcon');
prob.c = [0 0 0 1 1 1];
% Specify the non-conic part of the problem.
prob.a = sparse([1 1 2 0 0 0]);
prob.buc = 1;
prob.blx = [0 0 0 -inf -inf -inf];
prob.bux = inf*ones(6,1);
% Specify the cones.
prob.cones.type = [res.symbcon.MSK_CT_QUAD, res.symbcon.MSK_CT_RQUAD];
prob.cones.sub = [4, 1, 2, 5, 6, 3];
prob.cones.subptr = [1, 4];
for i=1:5
% Specify the changing bound
prob.blc = testBounds(i);
% Optimize the problem.
[r,res]=mosekopt('minimize',prob);
% Display the primal solution.
res.sol.itr.xx'
end
I tried to do this with parfor, but it isn't permitted. Unfortunately, MOSEK documentation doesn't go into detail about parallizing. How can I carry out the above in parallel?
The problem with your code is your use of the variable prob. While on an algorithmic level it is independent because each iteration of the loop uses it's own setting for blc and not uses any previous data, parfor does not support this use. Easiest solution is not to modify the variable prob but instead copy it in each iteration, making prob a broadcast and prob2 a local variable:
parfor ii=1:5
% Specify the changing bound
%copy broadcast variable prob to a temporary variable prob2
%this way the iteration has writing capabilities
prob2=prob
prob2.blc = testBounds(ii);
% Optimize the problem.
[r,res]=mosekopt('minimize',prob2);
% Display the primal solution.
res.sol.itr.xx'
end
Another issue with your code is the way you are returning data. parfor has no order when processing the data, thus just displaying it to the console will not give you any useful results. It's also slow. I don't know what exactly you need and what the datatypes are, thus I have not touched that part of the code. The code in my answer does the calculations but is not returning any results because res and r are both temporary variables.
N=5;
r = cell(1,N);
res = cell(1,N);
for ii=1:N
% Specify the changing bound
prob2=prob;
prob2.blc = testBounds(ii);
% Optimize the problem.
[r{ii},res{ii}]=mosekopt('minimize',prob2);
% Display the primal solution.
res{ii}.sol.itr.xx' %'// better not display at all during calculation
end
parfor does not allow for creation of variables within its bounds. Therefore I elected to preallocate r and res as cells, which can act the output storage. See the prob/ prob2 issue in #Daniel's answer
Related
I am trying to solve two coupled reaction diffusion equations in 1d, using pdpe, namely
$\partial_t u_1 = \nabla^2 u_1 + 2k(-u_1^2+u_2)$
$\partial_t u_2 = \nabla^2 u_1 + k(u_1^2-u_2)$
The solution is in the domain $x\in[0,1]$, with initial conditions being two identical Gaussian profiles centered at $x=1/2$. The boundary conditions are absorbing for both components, i.e. $u_1(0)=u_2(0)=u_1(1)=u_2(1)=0$.
Pdepe gives me a solution without prompting any errors. However, I think the solutions must be wrong, because when I set the coupling to zero, i.e. $k=0$ (and also if I set it to be very small, say $k=0.001$), the solutions do not coincide with the solution of the simple diffusion equation
$\partial_t u = \nabla^2 u$
as obtained from pdepe itself.
Strangely enough, the solutions $u_1(t)=u_2(t)$ from the "coupled" case with coupling set to zero, and the solution for the case uncoupled by construction $u(t')$ coincide if we set $t'=2t$, that is, the solution of the "coupled" case evolves twice as fast as the solution of the uncoupled case.
Here's a minimal working example:
Coupled case
function [xmesh,tspan,sol] = coupled(k) %argument is the coupling k
std=0.001; %width of initial gaussian
center=1/2; %center of gaussian
xmesh=linspace(0,1,10000);
tspan=linspace(0,1,1000);
sol = pdepe(0,#pdefun,#icfun,#bcfun,xmesh,tspan);
function [c,f,s] = pdefun(x,t,u,dudx)
c=ones(2,1);
f=zeros(2,1);
f(1) = dudx(1);
f(2) = dudx(2);
s=zeros(2,1);
s(1) = 2*k*(u(2)-u(1)^2);
s(2) = k*(u(1)^2-u(2));
end
function u0 = icfun(x)
u0=ones(2,1);
u0(1) = exp(-(x-center)^2/(2*std^2))/(sqrt(2*pi)*std);
u0(2) = exp(-(x-center)^2/(2*std^2))/(sqrt(2*pi)*std);
end
function [pL,qL,pR,qR] = bcfun(xL,uL,xR,uR,t)
pL=zeros(2,1);
pL(1) = uL(1);
pL(2) = uL(2);
pR=zeros(2,1);
pR(1) = uR(1);
pR(2) = uR(2);
qL = [0 0;0 0];
qR = [0 0;0 0];
end
end
Uncoupled case
function [xmesh,tspan,sol] = uncoupled()
std=0.001; %width of initial gaussian
center=1/2; %center of gaussian
xmesh=linspace(0,1,10000);
tspan=linspace(0,1,1000);
sol = pdepe(0,#pdefun,#icfun,#bcfun,xmesh,tspan);
function [c,f,s] = pdefun(x,t,u,dudx)
c=1;
f = dudx;
s=0;
end
function u0 = icfun(x)
u0=exp(-(x-center)^2/(2*std^2))/(sqrt(2*pi)*std);
end
function [pL,qL,pR,qR] = bcfun(xL,uL,xR,uR,t)
pL=uL;
pR=uR;
qL = 0;
qR = 0;
end
end
Now, suppose we run
[xmesh,tspan,soluncoupled] = uncoupled();
[xmesh,tspan,solcoupled] = coupled(0); %coupling k=0, i.e. uncoupled solutions
One can directly check by plotting the solutions for any time index $it$ that, even if they should be identical, the solutions given by each function are not identical, e.g.
hold all
plot(xmesh,soluncoupled(it+1,:),'b')
plot(xmesh,solcoupled(it+1,:,1),'r')
plot(xmesh,solcoupled(it+1,:,2),'g')
On the other hand, if we double the time of the uncoupled solution, the solutions are identical
hold all
plot(xmesh,soluncoupled(2*it+1,:),'b')
plot(xmesh,solcoupled(it+1,:,1),'r')
plot(xmesh,solcoupled(it+1,:,2),'g')
The case $k=0$ is not singular, one can set $k$ to be small but finite, and the deviations from the case $k=0$ are minimal, i.e. the solution still goes twice as fast as the uncoupled solution.
I really don't understand what is going on. I need to work on the coupled case, but obviously I don't trust the results if it does not give the right limit when $k\to 0$. I don't see where I could be making a mistake. Could it be a bug?
I found the source of the error. The problem lies in the qL and qR variables of bcfun for the coupled() function. The MATLAB documentation, see here and here, is slightly ambiguous on whether the q's should be matrices or column vectors. I had used matrices
qL = [0 0;0 0];
qR = [0 0;0 0];
but in reality I should have used column vectors
qL = [0;0];
qR = [0;0];
Amazingly, pdpe didn't throw an error, and simply gave wrong results. This should perhaps be fixed by the developers.
I want to set up the generic algorithm for a function that includes roughly 400 lines of script. The script itself is an optimisation process and I want to use the genetic algorithm to find the best input parameters into the optimisation process (M and OPratio). M lies between 0 and 10^7 and OPratio between 0 and 1.
The function of the script is:
NPVtotal = cut_off_optimisation(M,OPratio)
set up for the genetic algorithm:
nvars = 2; % Number of variables
LB = [0 0]; % Lower bound
UB = [10000000 1]; % Upper bound
X0 = [6670000 0.45]; % Start point
options.InitialPopulationMatrix = X0;
[M,OPratio,fval] = ga(cut_off_optimisation(M,OPratio),nvars,[],[],[],[],LB,UB)
I get following error:
Undefined function or variable 'M'.
I am new to optimisation and the genetic algorithm so would appreciate any help, please let me know if more information is necessary.
First of all I am assuming that the objective is to minimize the Objective function cut_off_optimisation.
Now first update your function to look like this
function y = cut_off_optimisation(x)
M=x(1);
OPratio=x(2);
%
% paste body of your currently used function here
%
y=NPVtotal ;
Now use this code to minimize your objective function.
nvars = 2; % Number of variables
LB = [0 0]; % Lower bound
UB = [10000000 1]; % Upper bound
X0 = [6670000 0.45]; % Start point
options = gaoptimset('PlotFcns',{#gaplotbestf},'Display','iter','InitialPopulation',X0);
[x,fval] = ga(#cut_off_optimisation,nvars,[],[],[],[],...
LB,UB,[],options);
M=x(1);
OPratio=x(2);
Update: If you don't want to update your function. Just run this main code. Keep the function NPVtotal = cut_off_optimisation(M,OPratio) in the same folder as that of the main code.
objectiveFunction=#(x)cut_off_optimisation(x(1),x(2));
nvars = 2; % Number of variables
LB = [0 0]; % Lower bound
UB = [10000000 1]; % Upper bound
X0 = [6670000 0.45]; % Start point
options = gaoptimset('PlotFcns',{#gaplotbestf},'Display','iter','InitialPopulation',X0);
[x,fval] = ga(objectiveFunction,nvars,[],[],[],[],...
LB,UB,[],options);
M=x(1);
OPratio=x(2);
fval
M
OPratio
Update: For getting final population members and fitness values. Replace the above ga function call statement to below statement.
[x,fval,exitflag,output,population,score] = ga(objectiveFunction,nvars,[],[],[],[],LB,UB,[],options);
M=x(1);
OPratio=x(2);
In here population will have the members of the final population and score will have fitness values for the final population. Default population size is 20. So you will have 20 rows in both the matrix. Number of columns in population will be equivalent to number of variables in the problem and score will be a column matrix. You can change the population size by adding option PopulationSize to gaoptimset.
options = gaoptimset('PlotFcns',{#gaplotbestf},'Display','iter','InitialPopulation',X0,'PopulationSize',30);
To know more about the options available for gaoptimset and their expected values and their {default values}. Go to matlab help and search for gaoptimset. There you will find a table with all these details. Here is the link from matlab website http://in.mathworks.com/help/gads/gaoptimset.html .There may be changes according to your matlab version. So its better to use help in matlab.
I have written the following piece of code:
M = [3 0 0; 0 2 0; 0 0 0.5] % mass matrix
i_vals = 1:1000:60e06; % values of k_12 from 1 to 600 million in steps of 1000
modes = zeros(3, length(i_vals));
for n=1:length(i_vals)
i = i_vals(n) % i is the value of k_12
K = [i+8e06 -i -2e06; -i i+2e06 -1e06; -2e06 -1e06 5e06]; % stiffness matrix
[V,L]=eig(K,M);
V(:,I)=V;
A = V(:, [1])
transpose(A)
modes(:, n) = A
end
loglog(i_vals, modes')
But the loop seems to go forever and I do now know what is wrong with it. The idea was to get the first column from matrix V, and see what happens to the 3 elements in this column when value of k_12 is changed.
I don't know how you make this run forever. To me it looks as if it won't run at all. This won't answer your question, but will hopefully help you on the way =)
What do you want to do with this line? V(:,I)=V; What is I? Was it supposed to be i? Btw, using i and j as variables in MATLAB is not recommended (however, if you don't use complex numbers in your field, you shouldn't care too much).
You have a loop that goes 60,000 times, with calculations of eigenvalues etc. That is bound to take time (although not forever, as you state it does). You should get the answer eventually (if only the rest of the code worked). The resolution of your plot would be more than accurate enough with 10,000 or even 100,000 steps at a time.
This part:
A = V(:, [1])
transpose(A)
modes(:, n) = A
could simply be written as:
modes(:,n) = V(:,1)';
assuming you want the transposed of A. transpose(A) does nothing in this context actually. You would have to do A = transpose(A) (or rather A = A') for it to work.
There are all kinds of problems with your code - some of which may contribute to your issue.
You are computing values of i on a linear scale, but ultimately will be plotting on a log scale. You are doing a huge amount of work towards the end, when there is nothing visible in the graph for your effort. Much better to use a log scale for i_vals:
i_vals = logspace(0, 7.778, 200); % to get 200 log spaced values from
% 1 to approx 60E6`
You are using a variable I that has not been defined (in the code snippet you provide). Depending on its size, you may find that V is growing...
You are using a variable name i - while that is legal, it overwrites a built in (sqrt(-1)) which I personally find troublesome.
Your transpose(A); line doesn't do anything (You would have to do A = transpose(A);).
You don't have ; after several lines - this is going to make Matlab want to print to the console. This will take a huge amount of resource. Suppress the output with ; after every statement.
EDIT the following program runs quickly:
M = [3 0 0.0;
0 2 0.0;
0 0 0.5]; % mass matrix
i_vals = logspace(0, 7.78, 200); % values of k_12 from 1 to 600 million in steps of 1000
modes = zeros(3, length(i_vals));
for n=1:length(i_vals)
i = i_vals(n); % i is the value of k_12
K = [i+8e06 -i -2e06; -i i+2e06 -1e06; -2e06 -1e06 5e06]; % stiffness matrix
[V,L]=eig(K,M);
modes(:, n) = V(:,1);
end
loglog(i_vals, modes')
Resulting graph:
If I didn't break anything (hard to know what you were doing with I), maybe this can be helpful.
I have a function of this form in MATLAB,
C=S*e^(L*t)*inv(S)*C_0
where my
S=[-2 -3;3 -2]
L=[0.5 0; 0 1.5]
C_0=[1; 1]
I need to plot this function with respect to time. My output C is a 2-by-1 matrix.
What I have done is computed e^L separately using b=expm(L) and then I inserted mpower(b,t) into the function. So my resulting function in the script looks like
b=expm(L);
C=S*mpower(b,t)*inv(S)*C_0;
Now, how should I go about plotting this w.r.t time. I tried defining the time vector and then using it, but quite obviously I get the error message which says matrix dimensions do not agree. Can someone give me a suggestion?
You can probably do this in a vectorised manner but if you're not worried about speed or succinct code, why not just write a for loop?
ts = 1 : 100;
Cs = zeros(2, length(ts) );
S = [-2 -3;3 -2];
L = [0.5 0; 0 1.5];
C_0 = [1; 1];
for ii = 1 : length(ts)
b = expm(L);
Cs(:,ii) = S*mpower(b,ts(ii))*inv(S)*C_0;
end
ts contains the time values, Cs contains the values of C at each time.
Not quite sure what this means.
"Warning: Matrix is singular to working precision."
I have a 3x4 matrix called matrix bestM
matrix Q is 3x3 of bestM and matrix m is the last column of bestM
I would like to do C = -Inverse matrix of Q * matrix m
and I get that warning
and C =[Inf Inf Inf] which isn't right because i am calculating for the camera center in the world
bestM = [-0.0031 -0.0002 0.0005 0.9788;
-0.0003 -0.0006 0.0028 0.2047;
-0.0000 -0.0000 0.0000 0.0013];
Q = bestM(1:3,1:3);
m = bestM(:,4);
X = inv(Q);
C = -X*m;
disp(C);
A singular matrix can be thought of as the matrix equivalent of zero, when you try to invert 0 it blows up (goes to infinity) which is what you are getting here. user 1281385 is absolutely wrong about using the format command to increase precision; the format command is used to change the format of what is shown to you. In fact the very first line of the help command for format says
format does not affect how MATLAB computations are done.
As found here, a singular matrix is one that does not have an inverse. As dvreed77 already pointed out, you can think of this as 1/0 for matrices.
Why I'm answering, is to tell you that using inv explicitly is almost never a good idea. If you need the same inverse a few hundred times, it might be worth it, however, in most circumstances you're interested in the product C:
C = -inv(Q)*m
which can be computed much more accurately and faster in Matlab using the backslash operator:
C = -Q\m
Type help slash for more information on that. And even if you happen to find yourself in a situation where you really need the inverse explicitly, I'd still advise you to avoid inv:
invQ = Q\eye(size(Q))
Below is a little performance test to demonstrate one of the very few situations where the explicit inverse can be handy:
% This test will demonstrate the one case I ever encountered where
% an explicit inverse proved useful. Unfortunately, I cannot disclose
% the full details without breaking the law, but roughly, it came down
% to this: The (large) design matrix A, a result of a few hundred
% co-registrated images, needed to be used to solve several thousands
% of systems, where the result matrices b came from processing the
% images one-by-one.
%
% That means the same design matrix was re-used thousands of times, to
% solve thousands of systems at a time. To add to the fun, the images
% were also complex-valued, but I'll leave that one out of consideration
% for now :)
clear; clc
% parameters for this demo
its = 1e2;
sz = 2e3;
Bsz = 2e2;
% initialize design matrix
A = rand(sz);
% initialize cell-array to prevent allocating memory from consuming
% unfair amounts of time in the first loop.
% Also, initialize them, NOT copy them (as in D=C,E=D), because Matlab
% follows a lazy copy-on-write scheme, which would influence the results
C = {cellfun(#(~) zeros(sz,Bsz), cell(its,1), 'uni', false) zeros(its,1)};
D = {cellfun(#(~) zeros(sz,Bsz), cell(its,1), 'uni', false) zeros(its,1)};
E = {cellfun(#(~) zeros(sz,Bsz), cell(its,1), 'uni', false) zeros(its,1)};
% The impact of rand() is the same in both loops, so it has no
% effect, it just gives a longer total run time. Still, we do the
% rand explicitly to *include* the indexing operation in the test.
% Also, caching will most definitely influence the results, because
% any compiler (JIT), even without optimizations, might recognize the
% easy performance gain when the code computes the same array over and
% over again. It probably will, but we have no control over when and
% wherethat happens. So, we prevent that from happening at all, by
% re-initializing b at every iteration.
% The assignment to cell is a necessary part of the demonstration;
% it is the desired output of the whole calculation. Assigning to cell
% instead of overwriting 'ans' takes some time, which is to be included
% in the demonstration, again for cache reasons: the extra time is now
% guaranteed to be equal in both loops, so it really does not matter --
% only the total run time will be affected.
% Direct computation
start = tic;
for ii = 1:its
b = rand(sz,Bsz);
C{ii,1} = A\b;
C{ii,2} = max(max(abs( A*C{ii,1}-b )));
end
time0 = toc(start);
[max([C{:,2}]) mean([C{:,2}]) std([C{:,2}])]
% LU factorization (everyone's
start = tic;
[L,U,P] = lu(A, 'vector');
for ii = 1:its
b = rand(sz,Bsz);
D{ii,1} = U\(L\b(P,:));
D{ii,2} = max(max(abs( A*D{ii,1}-b )));
end
time1 = toc(start);
[max([D{:,2}]) mean([D{:,2}]) std([D{:,2}])]
% explicit inv
start = tic;
invA = A\eye(size(A)); % NOTE: DON'T EVER USE INV()!
for ii = 1:its
b = rand(sz,Bsz);
E{ii,1} = invA*b;
E{ii,2} = max(max(abs( A*E{ii,1}-b )));
end
time2 = toc(start);
[max([E{:,2}]) mean([E{:,2}]) std([E{:,2}])]
speedup0_1 = (time0/time1-1)*100
speedup1_2 = (time1/time2-1)*100
speedup0_2 = (time0/time2-1)*100
Results:
% |Ax-b|
1.0e-12 * % max. mean st.dev.
0.1121 0.0764 0.0159 % A\b
0.1167 0.0784 0.0183 % U\(L\b(P,;))
0.0968 0.0845 0.0078 % invA*b
speedup0_1 = 352.57 % percent
speedup1_2 = 12.86 % percent
speedup0_2 = 410.80 % percent
It should be clear that an explicit inverse has its uses, but just as a goto construct in any language -- use it sparingly and wisely.