Using a Jacobian with MatCont - matlab

I am trying to solve a very large non-linear problem using the MatCont package. Due to the large number of dimensions, and the non-linear nature, I believe that supplying the Jacobian for my system to the MatCont algorithm will speed things up immensely. However, I cannot get it to recognise that it has a Jacobian to use!
As a minimal working example, I have modified the circle finder from the help documentation to include a Jacobian:
function out = curve()
out{1}=#curvefunc;
out{2}=#defaultprocessor;
out{3}=#options;
out{4}=#jacobian;
out{13}=#adapt;
end
function f=curvefunc(x)
f=x(1)^2+x(2)^2-1;
end
function J=jacobian(x)
disp('USE JACOBIAN')
J=[2*x(1) , 2*x(2)];
end
function varargout=defaultprocessor(varargin)
if nargin>2
varargout{3}=varargin{3};
end
varargout{2}=[0];
varargout{1}=0;
end
function option=options()
option=contset;
end
function [res,x,v]=adapt(x,v)
res=[];
end
I then try to run this program from the command line using
[x,v,s,h,f] = cont(#curve,[1;0]);
However, the response is
first point found
tangent vector to first point found
elapsed time = 0.2 secs
npoints curve = 300
Since I told it to output 'USE JACOBIAN' every time the Jacobian function was called, it is clear that MatCont is not using it.
How do I get the Jacobian to be used?

I solved my own problem! Seems I was quite close to getting it working. The below is a bit of a botch, so if anyone knows how to do it with options please post an answer also.
Firstly I edit the options settings so that when it performs the continuation it only locates the first point:
function option=options()
option = contset;
option = contset(option,'MaxNumPoints',1);
end
its fine for it to do this using numerical Jacobians, the first point is known very well in most problems. This is then called from a script or a function using the following:
[x,v,s,h,f] = cont(#curve,[1;0]);
global cds
cds.options.MaxNumPoints=[];
cds.symjac=1;
[x,v,s,h,f] = cont(x,v,s,h,f,cds);
The first line finds the initial point using numerical Jacobians, as it was set up to do. The continuer is then manually adjusted to firstly have no limit on the maximal number of points (this can be set to any appropriate number) and then the use of the user provided Jacobian is set to 1 (true). The continuer is then resumed with the new settings and uses the Jacobain properly.

Related

Matlab State Space Model Response system

I have a following lab where i was asked to write the command matlab lines for these questions:
If initial Conditions are: x(0)=[2;0].๐‘“๐‘–๐‘›๐‘‘ ๐‘กโ„Ž๐‘’ ๐‘Ÿ๐‘’๐‘ ๐‘๐‘œ๐‘›๐‘ ๐‘’ ๐‘ฆ(๐‘ก).
Find the response y(t) due to step input with Amplitude of
Find the Transfer Function for the above state space model
Derive back the state space model from (3).
a = [0,1;0,4];
b = [0;1];
c = [0 -5];
x0=[2;0];
sys = ss(a,b,c,2);
initial(sys,x0); % to get 1
[n,d]=ss2tf(a,b,c,0);
mySys_tf=tf(n,d) % to get 3
[num den] = tfdata(mySys_tf, 'v')
tf2ss(num,den) % to get 4
I have written this code but it seems like its not giving me any results in the response graph and thus i can't also solve 2 and it get error in 4 if you can help me out to check what is wrong
I believe that the error comes from the fact that the system is unstable. If you were to plot the system's reaction to a step input using step() then you will see how it goes to infinity. I also don't know how far you are into your controls course and if you've seen the root locus yet, but you can plot the root locus of the system via rlocus(sys) and you'll see that the real portion of the root is on the right half of the plane and therefore letting you know that the system is unstable.
The response is 0 and will stay zero as x(2) = 0. It requires an input u to get x(2) off zero. So the graph is totally fine.
use step(sys) and you will see the drop to -Inf. Optionally you can define the end-time. Call step(sys,1) to see a reasonable range.
You solved 3 & 4 yourself.
To check stability you simply need to ask MATLAB isstable(sys) (isn't it continent? Well, there is a danger that people will forget the theory behind it and how it is connected...)
To check observability: rank(obsv(sys)) and make sure that it is the same as the system matrix
assert(rank(obsv(sys)) == length(sys.A), 'System is not observable!')

How to set stop criteria for integer programming optimization in yalmip/matlab with xpress solver

I have an integer programming optimization problem, that I solve in matlab using yalmip and xpress as the solver. For the solver I want to set two stopping criteria - a time limit and an optimal gap limit.
I have tried to use the xpress functions MAXTIME and MIPRELSTOP, the matlab code compiles and runs the optimization but the stopping criteria are not transferred to the solver.
The relevant code part looks as follows:
Cons = [sum(sum((dVar_mat.*(x_mat.*y_vec))')) >= a]; %constraint
obj = sum(sum(dVar_mat.*z_mat)); %objective
ops = sdpsettings('solver', 'xpress', 'verbose', 2); %solver options
ops.xpress.MAXTIME = 10000; %set timelimit
ops.xpress.MIPRELSTOP = 0.05; %set relative gap as stop limit
solIP = optimize(Cons, obj, ops); % Solve
When I run the optimzation, a solution is found but significantly later than I would like it to stop. The report says:
STOPPING - MIPRELSTOP target reached (MIPRELSTOP=0.0001)
meaning the MIPRELSTOP target is still set at the default, which is 0.0001. Similarily, the optimization runs over the time limit, disregarding that stopping criterion as well.
How can I correctly set stopping criteria in matlab/yalmip/xpress?
Are you sure you are using the correct name and that it is exposed in the MATLAB interface, i.e. is that options visible in ops.xpress. I don't have xpress installed so I cannot test it.
(btw, YALMIP question are much better asked on the YALMIP Google groups forum)
The 'MAXTIME' control of Xpress Optimizer can be used with positive and negative values: with positive values for 'MAXTIME' when solving MIP problems the limit is only applied once a solution has been found, otherwise the solving continues until the first solution is found; a negative value means a hard stop, so for your case I would recommend that you try a value like -10000 as the time limit.
(See the documentation in the Xpress Optimizer Reference Manual, eg: https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/MAXTIME.html)

Change a constant in ODE calculations under particular conditions with a flag

I have an ODE for calculating how acidicity changes. Everything is working just fine, only I would like to change a constant whenever acidicity reaches a critical point. It is supposed to be some kind of irreversible effect I wish to simulate.
My constants are coming from a structure file (c) I load once in the ODE function.
[Time,Results] = ode15s(#(x, c) f1(x, c),[0 c.length],x0,options);
The main problem I have here is not telling Matlab to change the constant but remember if it happened already during the simulation once. so Matlab should take the irreversibly changed constant rather than the one I supply at the beginning.
I would like to write a flag that is saved while the ODE is running and an if condition, "if flag exists, change constant". How to do that?
UPDATE I:
PROBLEM SOLVED
Here a first own solution, it is not polished and requires a structure file approach. Which means, the constants which should suddenly changed upon an event, must be struct files which are handed in the ODE function into the function that should be evaluated (look above for the ODE syntax). The function accepts the inputs like this:
function [OUTPUT] = f1(t, x, c)
% So here, the constants all start with c. followed by the variable name. (because they are structs instead of globals)
%% write a flag when that event happens
if c.someODEevent <= 999 && exist ('flag.txt') == 0
dlmwrite ('flag.txt',1);
end
%% next iteration will either write the flag again or not. more importantly, if it exists, the constant will change because of this.
if exist ('flag.txt') == 2
c.changingconstant = c.changingconstant/2;
end
end
Please look into Horchlers kind answer where you have to take care that such a step may introduce inaccuracies and you have to be careful to check if your code does what it is supposed to do.
To do this accurately, you should use event detection within the ODE solver. I can't give you a specific answer because you've only provided the ode15s call it in your question, but you'll need to write an events function and then specify it via odeset. Something like this:
function acidity_main
% load c data
...
x0 = ...
options = odeset('Events',#events); % add any other options too
% integrate until critical value and stop
[Time1,Results1] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
x0 = Results(end,:); % set new initial conditions
% pass new parameters -it's not clear how you're passing parameters
% if desired, change options to turn off events for faster integration
[Time2,Results2] = ode15s(#(x,c)f1(x,c),[0 c.length],x0,options);
% append outputs, last of 1 is same as first of 2
Time = [Time1;Time2(2:end)];
Results = [Results1;Results2(2:end,:)];
...
function y=f1(x,c)
% your integration function
...
function [value,isterminal,direction] = events(x,c)
value = ... % crossing condition, evaluates to zero at event condition
isterminal = 1; % stop integration when event detected
direction = ... % see documentation
You'll want to use the events to integrate right to the point where the "acidicity reaches a critical point" and stop the integration. Then call ode15s again with the new value and continue the integration. This may seem crude, but it how this sort of thing can be done accurately.
You can see an example of basic event detection here. Type ballode in your command window to see the code for this. You can see a slightly more complex version of this demo in my answer here. Here's an example of using events to accurately change an ODE at specified times (rather than your case of specified state values).
Note: I find it strange that you're passing what you call "constants", c, as the second argument to ode15s. This function has strict input argument requirements: the first is the independent variable (often time), and the second is the array of state variables (same as your initial condition vector). Also if f1 only takes two arguments, #(x,c)f1(x,c) is superfluous โ€“ it's sufficient to pass in #f1.

How to set the stopping criterion of Matlab's fmincon to "output.stepsize" when "active-set" algorithm is used

How can the output.stepsize be used as a stopping criterion for fmincon when using the 'active-set' algorithm?
When I tried to solve a nonlinear constrained non-convex optimization problem, I observed that the output.stepsize option within 'PlotFcns' would be a better stopping criterion than the tolerances or maximum evaluations. But in the options argument structure, there is no such option.
I also noticed that fmincon uses nonlcon to solve the problem where output.stepsize is calcualted.
If I don't want to change the original code of either fmincon or nonlcon, how can I set an upper limit for output.stepsize to use as a stopping criterion for my optimization run?
Here's one way that you might try to accomplish this. I'm using one of the examples from the doc (there's also discussion of how to do exactly this there as well). I've simply added an output function that returns stop = true when the optimValues.stepsize field reaches a threshold. I also had to make sure that this field wasn't empty, as it appears to be at initialization.
function fmincontest
A = [-1 -2 -2;
1 2 2];
b = [0;72];
x0 = [10;10;10];
options = optimoptions('fmincon','Algorithm','active-set','OutputFcn',#outfun);
[x,fval,exitflag] = fmincon(#myfun,x0,A,b,[],[],[],[],[],options)
function f = myfun(x)
f = -x(1)*x(2)*x(3);
function stop = outfun(x, optimValues, state)
stop = ~isempty(optimValues.stepsize) && optimValues.stepsize < 0.05;
If you check the exit_flag output from fmincon, you'll see that it returns -1 now because the output function is stopping the optimization, again as indicated in the documentation. If you're already using a plot function, you can use that instead, as they have the same format.
You'll need to tailor this to your problem, adjust the threshold, and of course confirm that it works. I can't comment on how good of an idea this is. You should confirm that your error tolerances are still met satisfactorily for all cases. And I'd still want to ask why you can't specify appropriate 'TolCon' and 'TolX' tolerances to achieve what you need.

Problems with plotting in Matlab

Hey, I've got a problem plotting a function in Matlab.
I first run this:
format long
f = inline('-x.^2');
for i = 0:10
[I(i+1) h(i+1) tid(i+1)] = trapets(f,0,1,2^i);
end
trunk = I - log(2);
hold on
grid on
plot(log(h),log(trunk),'r+')
t = -7:0;
c = polyfit(log(h),log(trunk),1);
yy = polyval(c,t);
plot(t,yy)
grid off
hold off
koefficienter = real(c)
and after that I run this file:
hold on
plot(h,trunk,'r+:','linewidth',2)
axis([0 0.6 0 0.0014])
Thing is, I don't get any errors, and the plot windows pops up with axes and all, but there is no graph to be found. It's just an empty window with two axes.
Anyone got any ideas?
Edit:
Okay, so I'm new to this site and couldn't find the reply button, so I add a reply here instead.
#woodchips :
I just realized that I hadn't given you all the information for this problem.. Sorry about that, anyhow I would really appreciate it if someone had the time to help me with this, it would seriously make my week.
This is the part I accidentally left out:
function [ I,h,tid ] = trapets(
f,a,b,n )
h=(b-a)/n;
tic; I=(f(a)+f(b));
for k=2:2:n-2
I = I+2*f(a+k*h);
end
for k = 1:2:n-1
I = I + 4*f(a+k*h);
end
I = I * h/3;
tid = toc;
end
Edit 2: So, I think that the graph I'm seeking is actually getting plotted in the first code that I wrote, the problem is that the variabe 'I' is not changing, which I expect it to do, although the variabels 'n' and 'h' do change. If 'I' was working correctly, I would probably get the right graph (hopefully). Any ideas, anyone?
Unfortunately the home computer I had with Matlab on it died the other day so I can't test anything. First thing I can think of if to simply run step by step through the code and see if the results of the math are what you are expecting. For instance Matlab was primarily made and runs as a matrix calculator if I recall correctly. As such most of the simple math doesn't function as it would punching it in a calculator. An example would be that 2^i needs to be 2.^i to operate correctly in some cases. Same with .* and ./ to use the singular scalar verses the matrices math.
The best way to find out what is going wrong is to iterate through the math a few times to ensure that it is being performed as expected. Once that is verified then you can move on to looking at plotting formatting.