MATLAB Answers

expression is too large, symengine can't calculate

20 views (last 30 days)
Wang Hong
Wang Hong on 18 Jan 2020 at 5:02
Commented: Walter Roberson on 9 Feb 2020 at 18:21
I use symbolic expression to calculate sensitivity equasions of ODEs with 19 ODEs and 42 variables. And the error message is "the expression is too large , symengin can't calculate " when using it to calculate the second order sensitivity equations. I checked the dimension is more than 3 ten thousand and it isn't the sparse matrix. I debug into the symbolic there is no sourcecode, how do I do next?
Part codes like next:
function obj = compute_2nd_order_sensitivity_equations(obj)
M = obj.M;
N = obj.N;
if isempty(obj.S) || isempty(obj.dS) || isempty(obj.S0)
obj = obj.compute_1st_order_sensitivity_equations;
end
[SS,dSS,SS0] = sensitivity_equations_another([obj.x;obj.S(:)], obj.theta, [obj.dx;obj.dS(:)], [obj.x0;obj.S0(:)]);
SS(1:M,:)=[]; dSS(1:M,:)=[]; SS0(1:M,:)=[]; % remove the first order sensitivity equations
obj.SS = reshape(SS,M,N,N) ; % reshape the 2nd order equations
obj.dSS = reshape(dSS,M,N,N);
obj.SS0 = reshape(SS0,M,N,N);
obj.ODE_2nd_order_sensitivity_rhs = matlabFunction(obj.dx,obj.dS(:),obj.dSS(:),'vars', {'t', obj.x,obj.S(:),obj.SS(:), obj.theta}); % define the right hand side of the ODE as a function of time, system states + sensitivity, and parameter
obj.ODE_2nd_order_sensitivity_init = matlabFunction(obj.x0,obj.S0(:),obj.SS0(:),'vars', {obj.theta}); % define the initial condition as a function of parameters
end
symengine give error messages in function of matlabFunction
......
else
body = mup2matcell(funs, opts.Sparse);
body = renameInputs(body,vars,inputs);
g = symengine('makeFhandle',varnames,body);
end

  1 Comment

Walter Roberson
Walter Roberson on 18 Jan 2020 at 7:38
It would be more common to use odeFunction() instead of matlabFunction in constructing equations ?

Sign in to comment.

Answers (2)

Walter Roberson
Walter Roberson on 18 Jan 2020 at 7:51
Edited: Walter Roberson on 18 Jan 2020 at 7:51
Create
eqns = [obj.dx,obj.dS(:);obj.dSS(:)];
Now break that up into chunks. For example:
At_a_time = 10;
num_eqn = length(eqns);
num_chunks = ceil(num_eqn ./ At_a_time);
fh = cell(num_chunks, 1);
for K = 1 : At_a_time : num_eqn - At_a_time
fn{K} = matlabFunction(eqns(K:K+At_a_time-1), 'vars', {'t', obj.x,obj.S(:),obj.SS(:), obj.theta});
end
if num_chunks * At_a_time ~= num_eqn %you should double-check the boundary conditions here
fn{K+1} = matlabFunction(eqns(K+At_a_time:end), 'vars', {'t', obj.x,obj.S(:),obj.SS(:), obj.theta});
end
And now:
obj.ODE_2nd_order_sensitivity_rhs = @(varargin) cell2mat(cellfun(@(FH) FH(varargin{:}), fn, 'uniform', 0));
which should execute the handles one at a time and form a vector of the results.
Yes, this is a bit of a hack, but if it gets the job done then it gets the job done.

  3 Comments

Wang Hong
Wang Hong on 19 Jan 2020 at 5:17
@ Walter Roberson: Thanks a lot! I will try it to check whether it can continue to calculate
Wang Hong
Wang Hong on 23 Jan 2020 at 4:50
@Walter Roberson, Though the origianl problem can be executed, the next steps face another obtacle. Owing to the result of is so different, when we compute ode45 with the function handle,it gives the error information is : the number of input parameters is not enough , and we call it like this:
[t,y] = ode45(@(t,x_values)obj.ODE_2nd_order_sensitivity_rhs(t,x_values,para),obj.time_points_to_evaluate,obj.ODE_2nd_order_sensitivity_init(para));
Walter Roberson
Walter Roberson on 23 Jan 2020 at 5:20
You use matlabFunction with 'vars' and provide a cell array with five elements. That is going to convert into a function that expects five parameters. However you are only passing three parameters to it. It needs t, x S, SS, and theta parameters.

Sign in to comment.


Wang Hong
Wang Hong on 9 Feb 2020 at 14:53
@Walter Roberson,
I tried different methods, such as:
1. p_values={obj.x,obj.S(:),obj.SS(:)};
options = odeset('RelTol',1e-1);
[t,y] = ode45(@(t,x_values)obj.ODE_2nd_order_sensitivity_rhs(t,obj.dx,obj.dS(:),obj.dSS(:),obj.para),obj.time_points_to_evaluate,obj.ODE_2nd_order_sensitivity_init(para),options,p_values);
and
2. p_values={obj.x,obj.S(:),obj.SS(:)};
options = odeset('RelTol',1e-1);
[t,y] = ode45(@(t,x_values)obj.ODE_2nd_order_sensitivity_rhs(t,x_values,obj.para),obj.time_points_to_evaluate,obj.ODE_2nd_order_sensitivity_init(para),options,p_values);
but the error information are both : too many input arguments, what makes me confusing are the bold parts ODE_2nd_order_sensitivity_rhs(t,obj.dx,obj.dS(:),obj.dSS(:),obj.para) and p_values, I think the p_values is the input arguments and what is the previous?
My God , I don't know how to pass the parameters

  1 Comment

Walter Roberson
Walter Roberson on 9 Feb 2020 at 18:21
MATLAB is going to detect that you did not pass a nonlinear constraint function after the boundary conditions. It is then going to see the p_values as an extra parameter that it must pass to the function along with the regular two parameters, so it would pass it along with t and x_values to your anonymous function that you defined as only expecting two parameters.
The function you call does not appear to expect p_values as a parameter.

Sign in to comment.

Sign in to answer this question.