We are given four points, assumed to be ordered:
A = sort(randn(1,4))
I want to find the maximum possible number x in the interval 0<x<1 such that
A(1)<x<A(2) or A(3)<x<A(4)
Some examples:
A = [-1.4924 0.3004 1.6630 2.1204], x = 0.3004
A = [-0.4754 0.1353 0.6552 1.3873]; x = 1.0000
A = [-1.0213 -0.4521 -0.0905 0.1000]; x = 0.1000
A = [-1.8258 -0.5790 -0.4568 -0.1950]; x = 0.0000
A = [ 1.5000 2.0000 2.5000 3.0000]; x = 1.0000
Can you suggest a compact code to do this job, without having to list all the possible scenarios using if statements?
Having tried to do this with no if statements, I found that the readability of the code was greatly diminished. Note that there is only a single if statement in the code below while several other if statements could be substituted for the logical comparisons.
All of your tests pass and the code remains very concise (9 lines without the comments and loop over all of the tests).
A = [[-1.4924 0.3004 1.6630 2.1204];
[-0.4754 0.1353 0.6552 1.3873];
[-1.0213 -0.4521 -0.0905 0.1000];
[-1.8258 -0.5790 -0.4568 -0.1950];
[ 1.5000 2.0000 2.5000 3.0000]];
for i = 1:size(A,1)
% Reshape A so that each set of 2 entries are compared
Atmp = reshape(A(i,:),2,2);
% Find any valid entries
Valid = Atmp > 0 & Atmp < 1;
Ind_Valid = find(Valid == 1);
if (~isempty(Ind_Valid))
% If there are valid entries, return:
% max(A(ind),0) if the entry is the 1st of the pair
% max(A(ind),1) if the entry is the 2nd of the pair
max_Ind = max(Ind_Valid);
x = max(Atmp(max_Ind),mod(max_Ind,2))
else
% If there are no valid entries, return:
% 0 if max A < 0
% 1 if max A > 1
x = max(Atmp(:)) > 0
end
end
Output:
x =
0.3004
x =
1
x =
0.1000
x =
0
x =
1
Related
i am trying to save the output of the following function (it gives two outputs for every iteration of input 1, the rest remains the same).
The function creates a stress testing for an interbank market, testing for the effects (output is capital_losses and defaulted_banks) of default of every bank in the sample, i.e. input1 must go from 1:(length(input2), 4 in the code provided here, 300+ in the final code, so i need a loop
here a sample of one iteration with bank 3 defaulting
input1 = 3; % default_bank
input2=[100000;200000;300000;400000]; % capital levels in the function
input3 = ...
[70000, 15000, 24000, 52453;
23420, 24252, 10000, 35354;
98763, 45666, 96555, 05000;
09800, 54444, 04336, 67520]; % interbank loans in the function
input4 = 1;
input5 = .35;
input6 = 1;
% function calls on above inputs
[capital_losses defaulted_banks] = interbank_model( ...
input1, input2, input3, input4, input5, input6)
this is the standard output for one iteration with default_bank=3, but I need this for 300+, so a loop would be helpful...
capital_losses3 =
1.0e+05 *
0.5857
0.2598
3.0000
0.0609
defaulted_banks3 =
0
0
1
0
I would like to get the output for every defaulted bank, i.e. default_bank=1:4 to be displayed by the for loop as follows:
capital_losses_all =
1.0e+05 *
1.0000 0.2320 0.5857 0.5857
0.2867 2.0000 0.2598 0.2598
1.0716 0.4917 3.0000 3.0000
0.2816 0.6682 0.0609 0.0609
defaulted_banks_all =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
This was manually generated, but how do i store the values in matrices?
Thanks for your help. (I had a similar question before but the editing and commenting got very confusing so here's my improved cry for help... )
Chris
Very general answer (adapt for your need):
valuesThatChange = [1 3 5 4 2]; % different for each iteration in the loop
% values that don't change:
a=1;
b=2;
c=3;
N = numel(valuesThatChange);
% create storage for results:
results = zeros(4, N);
% loop N times
for ii=1:N
results(:,ii) = functionCall(valuesThatChange(ii), a, b, c); % returns a 4 element result
end
Now you have the result from your function for each loop in a 4xN matrix.
Problem : I need to clamp each of the elements of P matrix in the range [-1,1]. I have used the code MinMaxCheck provided but this code works only for vectors. So, I have modified it to work for matrix. The modified function code MinMaxCheckMatrix does change only the first column but the second column elements are not checked nor clamped. I am unable to understand why the entire P matrix is not getting affected. Please help in rectifying.
SomeVector = [20 0
-20 1
5 0.9
1.1 0.2
10 20];
for rows =1:5
P(rows,:) = SomeVector;
min_range(rows,:)=-1;
max_range(rows,:)=1;
end
P = MinMaxCheckMatrix(min_range, max_range, P);
**Function**
function [ A2comp ] = MinMaxCheckMatrix( minimum, maximum, A2comp )
[row col] = size(minimum);
for i=1:row
for j=1:col
if(maximum(i,j)<A2comp(i,j)||minimum(i,j)>A2comp(i,j))
if(maximum(i,j)<A2comp(i,j))
A2comp(i,j)=maximum(i,j);
else A2comp(i,j)=minimum(i,j);
end
end
end
end
This is the result that I got:
P =
1.0000 0
-1.0000 1.0000
1.0000 0.9000
1.0000 0.2000
1.0000 20.0000
Unless I'm missing something, that seems like a very overcomplicated way to do this:
P(P < -1) = -1;
P(P > 1) = 1;
or, fancier:
function mat = clamp(mat, minval, maxval)
mat(mat < minval) = minval;
mat(mat > maxval) = maxval;
It's because size(minimum) is not the same as size(A2comp).
Looking at
P(rows,:) = SomeVector;
min_range(rows,:)=-1;
max_range(rows,:)=1;
The number of columns is determined by the right-hand side, and so min_range and max_range as created with only one column.
You could just vectorize this:
function [ A2comp ] = MinMaxCheckMatrix( minimum, maximum, A2comp )
A2comp = bsxfun(#max, A2comp, minimum);
A2comp = bsxfun(#min, A2comp, maximum);
end
I usually like writing something like this:
function [ mO ] = ClampArray( mO, minVal, maxVal )
mO = max(min(mO, maxVal), minVal);
end
Now all you need is P = ClampArray(P, -1, 1);.
I wanted to be:
arr(2,1) = arr(2,1) + abs(5.0 minus 5.1);% where I(1,a) is 5.0 and I(1,a+1)is 5.1
Why couldn't I add the below two together? I got this error message:
Subscripted assignment dimension mismatch (size [1 x 1] ~= size [1 x :?]).
Function 'MATLAB Function' (#620.435.485), line 23, column 2:
"arr(count,1) = arr(count,1) + abs(I(1,a)-I(1,a+1))"
Launch diagnostic report.
'I' is declared in worskspace as:
I =
5.0000 5.1000 5.2000 5.2000
90.0000 85.0000 80.0000 20.0000
integ_signal=zeros(5,4);
a=zeros(10);
arr=zeros(5,4);
count=2;
a=1;
integ_signal(count,1)= integ_signal(count-1,1);
arr(count,1) = integ_signal(count,1);
arr(count,1) = arr(count,1) + abs(I(1,a)-I(1,a+1));
The system is shown here. The complete code is below:
function integ_signal= fcn(I,V,count,oldval)
integ_signal=zeros(5,1);
a=zeros(10);
arr=zeros(2,4);
%b=zeros(10);
integ_signal=oldval;
coder.extrinsic('load');
load('data.mat','I');
a=1;
%b=1;
if count==1
integ_signal(count,1) = 10; % Initial Condition
end
if count>1
integ_signal(count,1)= integ_signal(count-1,1);
arr(count,1) = integ_signal(count,1);
arr(count,1) = arr(count,1) + abs(I(1,a)-I(1,a+1));
end
a=a+1;
% b++;
end
Dear Sir, I keep getting this error, my desired output is to get abs(I(2,ii(a))-I(2,ii(a)-1) so that when ii(a)=2, I want I(2,2) minus I(2,1) which is 5.1 minus 5.0 : Index expression out of bounds. Attempted to access element 2. The valid range is 1-1.
"2"
. at this line:
arr(1,ii(a)) = arr(1,ii(a)) + abs(I(2,ii(a))-I(2,ii(a)-1));.
I define I as the following in .mat file:
save data -v7.3 'I'
load('data.mat','I');
I =
Columns 1 through 6
0 1.0000 2.0000 3.0000 4.0000 5.0000
5.0000 5.1000 5.2000 5.2000 5.5000 5.9000
Column 7
6.0000
6.0000
I guess you call your code with count as a vector. Also, it seems like you're missing a loop. (If not, why the a = a + 1?)
a = zeros(10);
followed by
a = 1;
does not make much sense. What is your input variable I? What do you want load('data.mat','I') to do?
If I'm correct, try something like:
for ii = 1:length(count)
if count(ii) == 1
integ_signal(count(ii),1) = 10; % Initial Condition
end
if count(ii) > 1
integ_signal(count(ii),1)= integ_signal(count(ii)-1,1); % Or, (count(ii-1),1)
arr(count(ii),1) = integ_signal(count(ii),1);
arr(count(ii),1) = arr(count(ii),1) + abs(I(1,a)-I(1,a+1));
end
a = a + 1;
end
You probably need to tweak this in some way, but I think it may help you a bit.
I keep getting this error:
Index expression out of bounds. Attempted to access element 2. The
valid range is 1-1."2".
My desired output is to get
abs(I(2,ii(a))-I(2,ii(a)-1)
so that when ii(a)=2, I want I(2,2) minus I(2,1) which is 5.1 minus 5.0
The error is due to this line:
arr(1,ii(a)) = arr(1,ii(a)) + abs(I(2,ii(a))-I(2,ii(a)-1));.
I define I as the following in .mat file:
save data -v7.3 'I'
load('data.mat','I');
I =
Columns 1 through 6
0 1.0000 2.0000 3.0000 4.0000
5.0000 5.1000 5.2000 5.2000 5.5000
The code:
function arr= fcn(I,count,oldval)
persistent integ_signal
if isempty( integ_signal)
integ_signal=zeros(1,5)
end
persistent a
if isempty(a)
a=zeros(1)
end
arr=zeros(1,5);
ii=zeros(1,5);
aa=zeros(2,5);
integ_signal=oldval;
coder.extrinsic('load');
aa=load('data.mat','I');
if count==1
a=1;
ii(a)=count;
integ_signal(1,ii(a)) = 10; % Initial Condition
end
if count ~= 1
a=count;
ii(a)=count;
integ_signal(1,ii(a))= integ_signal(1, ii(a)-1);
arr(1,ii(a)) = integ_signal(1,ii(a));
arr(1,ii(a)) = arr(1,ii(a)) + abs(aa(2,ii(a))-aa(2,ii(a)-1));
end
a = a + 1;
end
I want to split a matrix columnwise into 3 segments and do a calculation on it (mean()). Is there a way to get this without a for-loop, as I did in this provided sample?
M = [2 4 9; 50 50 200; 30 0 0];
M = [M 10*M]
N = length(M);
seg = 3 % split in lets say 3 parts
segLen = round(N/seg)
segBeg = (((1:seg)-1) * segLen)+1 % start indices
segEnd = segBeg + segLen -1 % end indices
for i = 1: length(segBeg)
mean(M(:,segBeg(i):segEnd(i)),2)
end
Thank you!
Think outside the box: use the 3rd dimension:
r=reshape(M,size(M,1),segLen,[])
squeeze(mean(r,2))
The first line produces a 3d array with the first matrix at r(:,:,1), the second at r(:,:,2), ... (use M(:,1:seg*segLen) instread of M if the number of columns is not divisible by segLen).
mean(r,2) produces a nrows-by-1-by-seg array, squeeze makes a nrows-by-seg matrix out of it again.
You can use arrayfun together with cell2mat
result = cell2mat(arrayfun(#(x,y) mean(M(:,x:y),2), segBeg, segEnd,...
'UniformOutput', false))
This results in
result =
1.0e+03 *
0.0030 0.0145 0.0650
0.0500 0.3500 1.2500
0.0150 0.1500 0
where each column represents the mean across one submatrix.
Another solution using blockproc (like suggested by #DennisJaheruddin in the comments) could look like this
myFun = #(x) mean(x.data,2);
result2 = blockproc(M, [N, segLen], myFun)
This also results in
result2 =
1.0e+03 *
0.0030 0.0145 0.0650
0.0500 0.3500 1.2500
0.0150 0.1500 0
Note that blockproc can take advantage of parallel processing if the flag 'UseParallel' is set to true, i.e., result2 = blockproc(M, [N, segLen], myFun, 'UseParallel', true)
You can do for your example case
mean1 = mean(M(:,1:segLen))
mean2 = mean(M(:,segLen+1:N-segLen-1))
mean3 = mean(M(:,N-segLen:end))