find_loops_vset
PURPOSE 
Determines loop lists for an ODE system given by a function and at multiple sets of variables. Loop lists are reported if signs of Jacobian matrix have changed.
SYNOPSIS 
function[loop_rep,loop_rep_index,jac_rep,jac_rep_index]=find_loops_vset(func, vset, max_num_loops,compute_full_list)
DESCRIPTION 
FIND_LOOPS_VSET Detect feedback loops from sets of variable values of
interest.
LOOP_REP = FIND_LOOPS_VSET(FUNC, VSET, MAX_NUM_LOOPS) can be used as a wrapper for the
functions numerical_jacobian_complex() and find_loops(). For the ODE function y'=FUNC(y),
it returns the loop list at column vector of variable values y=VSET.
FUNC should be a function handle that depends on the variable values
only; parameters and time have to be set to fixed values.
MAX_NUM_LOOPS is an optional input parameter that restricts the maximal
number of reported loops (default: 1e6). LOOP_REP is a cell array of length
1, LOOP_REP{1} returns the loop list as Matlab Table (formatted as in find_loops()).CROSS-REFERENCE INFORMATION 
This function calls:
- find_edge FIND_EDGE Find loops in a loop list that contain a certain direct
- find_loops FIND_LOOPS Compute feedback loops from Jacobian or adjacency matrix.
- numerical_jacobian_complex NUMERICAL_JACOBIAN_COMPLEX Determine Jacobian matrix via finite
- workflow_LoopDetect_Matlab % LoopDetect: Feedback Loop Detection in ODE models in MATLAB
SOURCE CODE 
0001 function[loop_rep,loop_rep_index,jac_rep,jac_rep_index]=find_loops_vset(func, vset, max_num_loops,compute_full_list) 0002 %FIND_LOOPS_VSET Detect feedback loops from sets of variable values of 0003 %interest. 0004 % 0005 % LOOP_REP = FIND_LOOPS_VSET(FUNC, VSET, MAX_NUM_LOOPS) can be used as a wrapper for the 0006 % functions numerical_jacobian_complex() and find_loops(). For the ODE function y'=FUNC(y), 0007 % it returns the loop list at column vector of variable values y=VSET. 0008 % FUNC should be a function handle that depends on the variable values 0009 % only; parameters and time have to be set to fixed values. 0010 % MAX_NUM_LOOPS is an optional input parameter that restricts the maximal 0011 % number of reported loops (default: 1e6). LOOP_REP is a cell array of length 0012 % 1, LOOP_REP{1} returns the loop list as Matlab Table (formatted as in find_loops()). 0013 0014 % [LOOP_REP,LOOP_REP_INDEX]= FIND_LOOPS_VSET(FUNC, VSET) 0015 % Multiple sets of variable values can be supplied to the function which reports 0016 % loop lists corresponding to different classes of Jacobian matrices (those 0017 % with similar sign structure). VSET can be, for example, the transposed 0018 % solution vector when solving the ODE system with 0019 % one of the Matlab solvers, or concatenations of other sets of 0020 % variable values. For an ODE system of size _n_, the dimension of VSET should 0021 % be _nxk_ with _k_ being the number of different sets of variable values at 0022 % which loops should be detected (i.e. k column vectors of length n are concatenated). 0023 % LOOP_REP_INDEX has length k (one entry for each set of variable values in VSET) 0024 % and captures as an integer index which loop list corresponds to which set 0025 % of variable values. Please note that loop lists can be identical despite 0026 % belonging to different sign classes of Jacobians. 0027 % 0028 % [LOOP_REP,LOOP_REP_INDEX]= FIND_LOOPS_VSET(FUNC, VSET,MAX_NUM_LOOPS,COMPUTE_FULL_LIST) 0029 % Syntax as before. If the logical input COMPUTE_FULL_LIST is set to false (default: true), 0030 % the classes of Jacobians are further reduced and loop lists are not re-computed 0031 % for Jacobians that clearly do not allow for altered loop lists. This is 0032 % the case if no new regulation appear and 0033 % only signs of regulations are altered that are not member of any loop. 0034 % Loop lists can still be identical (e.g. if two sign 0035 % switches occur that are both affecting the same loops). 0036 % 0037 % [LOOP_REP,LOOP_REP_INDEX,JAC_REP,JAC_REP_INDEX]= FIND_LOOPS_VSET(_) 0038 % Syntax as before. JAC_REP returns the different detected signed Jacobians, 0039 % JAC_REP_INDEX gives the index of the signed Jacobian for each set of 0040 % variable values. Only if COMPUTE_FULL_LIST is set to false, LOOP_REP can 0041 % contain 0042 % fewer elements than JAC_REP, otherwise both have the same number of elements. 0043 % 0044 % Examples 0045 % Determine the loop list for a function at one set of variable values 0046 % klin=[165,0.044,0.27,550,5000,78,4.4,5.1]; 0047 % knonlin=[0.3,2]; 0048 % loop_list = find_loops_vset(@(x)func_POSm4(0,x,klin,knonlin),[1 2 1 1]) 0049 % 0050 % Determine the loop list along the solution of an ODE system, report at 0051 % most 100000 loops and do not compute the loop list for all Jacobians. 0052 % sol=dlmread('li08_solution.tsv','delimiter','\t'); 0053 % [loop_rep,loop_rep_index,jac_rep,jac_rep_index]=find_loops_vset(... 0054 % @(x)func(0,x), sol(2:end,:), 1e5, false) 0055 % 0056 % See also: FIND_LOOPS(), NUMERICAL_JACOBIAN_COMPLEX() 0057 0058 0059 0060 if nargin<3 0061 max_num_loops=1e6; 0062 end 0063 if nargin<4 0064 compute_full_list=true; 0065 end 0066 0067 %determine the initial Jacobian and loop list 0068 J_ini=numerical_jacobian_complex(func,vset(:,1)); 0069 0070 vset_count=size(vset,2); %how many different sets of variable values 0071 0072 %determine all different Jacobian matrices (signs only) 0073 Jsig_tab=zeros(1,size(vset,2)); 0074 Jsig_rep={sign(J_ini)}; 0075 for i=1:vset_count 0076 J_temp=numerical_jacobian_complex(func,vset(:,i),1e-8); 0077 %check whether the new Jacobian is different from the Jacobians found earlier 0078 for j=1:length(Jsig_rep) 0079 disttemp=max(max(abs(sign(J_temp)-Jsig_rep{j}))); 0080 if disttemp==0 %if another Jacobian is the same 0081 Jsig_tab(i)=j; 0082 break 0083 end 0084 end 0085 if Jsig_tab(i)==0 %if no other Jacobian was the same before 0086 Jsig_rep{end+1}=sign(J_temp); %save the Jacobian 0087 Jsig_tab(i)=length(Jsig_rep); 0088 end 0089 end 0090 jac_rep=Jsig_rep; 0091 jac_rep_index=Jsig_tab; 0092 0093 %determine loops for the different Jacobians 0094 %loops should only differ if 0095 % - switch from zero no nonzero 0096 % - switch of an entry that is an edge of a loop 0097 0098 loop_tab=zeros(1,size(vset,2)); 0099 loop_tab(Jsig_tab==1)=1; %set the loop index according to the Jacobian that belongs 0100 loop_rep={find_loops(J_ini,max_num_loops)}; %J_ini equals Jsig_rep{1} 0101 0102 if compute_full_list %if we should compute the full loop list 0103 0104 for i=2:length(Jsig_rep) %check each Jacobian (if there are more than 1) 0105 J_temp=Jsig_rep{i}; 0106 loop_rep{end+1}=find_loops(J_temp,max_num_loops); 0107 end 0108 loop_tab=jac_rep_index; %loop identity equals Jacobian identity 0109 0110 else %if we should not compute the full loop list, more efficient (exclude Jacobians that cannot generate different loop lists) 0111 0112 for i=2:length(Jsig_rep) %check each Jacobian (if there are more than 1) 0113 J_temp=Jsig_rep{i}; 0114 %determine if there is a switch from zero to nonzero 0115 switch_to_nonzero=zeros(1,i-1); 0116 for j=1:(i-1) %compare with all earlier Jacobians 0117 switch_to_nonzero(j)=sum(sum(abs(J_temp(Jsig_rep{j}==0))))>0; 0118 end 0119 %determine if the sign switches of an edge that is contained in a loop 0120 change_in_a_loop=zeros(1,i-1); 0121 for j=1:(i-1) %compare with all earlier Jacobians 0122 if switch_to_nonzero(j)==0 %we only have to check this if we don't already have another change 0123 [target_node_ind, source_node_ind]=find(not(J_temp-Jsig_rep{j}==0)); 0124 for k=1:length(target_node_ind) 0125 change_in_a_loop(j)=not(isempty(find_edge(loop_rep{loop_tab(find(Jsig_tab==j,1))},... %the loop list corresponding to Jacobian j 0126 source_node_ind(k),target_node_ind(k)))); 0127 if change_in_a_loop(j)==1 %in case there is a change in at least one edge 0128 break 0129 end 0130 end 0131 end 0132 end 0133 %check if there is any earlier Jacobian that is neither changed from zero to 0134 %nonzero for J_temp, nor any change in an edge of a loop is observed --> this 0135 %Jacobian will lead to exactly the same loops as the Jacobian of 0136 %interest, J_temp 0137 loop_ind_temp=find(switch_to_nonzero==0 & change_in_a_loop==0,1); %find only the first Jacobian that has the same profile 0138 if isempty(loop_ind_temp) %in case no Jacobian coincides, we compute the loops anew 0139 loop_rep{end+1}=find_loops(J_temp,max_num_loops); 0140 loop_tab(Jsig_tab==i)=length(loop_rep); 0141 else %in case the Jacobian is similar to another Jacobian 0142 %(e.g. because the sign switch appeared in a nonzero entry that 0143 %does not generate any loop) we just use that Jacobian 0144 loop_tab(Jsig_tab==i)=loop_ind_temp; 0145 end 0146 end 0147 end 0148 0149 loop_rep_index=loop_tab; 0150 0151 end 0152
Generated on Wed 24-Jun-2020 09:38:33 by m2html © 2005