If statements vs conditions

1 vue (au cours des 30 derniers jours)
Joy Shen
Joy Shen le 6 Sep 2023
Commenté : Joy Shen le 7 Sep 2023
Hi all,
I'm trying to set conditions to define some later operations.
I'm essentially simulating Esim4 which can be a value from 0 to 10, and fgsim which is a binary variable indicating whether something is installed (1) or missing (0). I'm then trying to calculate Asim_door. If fg installed (i.e., fgsim=1) and Esim4 is below n_fg, then Asim_door=0. If fg is installed and Esim4 is above n_fg, then Asim_door=Asim_door/A_fg. Otherwise if fg is not installed then Asim_door is not changed.
I get an error "Unable to perform assignment because the left and right sides have a different number of elements." when I attempt this with conditions as indicated by the %%%%.
What's the difference between doing it this way and an if statement?
% CVol3 sim
for iCombCVol3=1:size(IndMatCVol3) %Parent PS1 has 3 states for child node Vi
% EFH loc 4 sim
EFH4_a=[]; EFH4_a=ExtSurgeBinEdges_Lo(IndMatCVol3(iCombCVol3,4));
EFH4_c=[]; EFH4_c=ExtSurgeBinEdges_Hi(IndMatCVol3(iCombCVol3,4));
pdEFH4=[]; pdEFH4=makedist('Uniform',EFH4_a,EFH4_c);
Esim4=[]; Esim4=random(pdEFH4,[Nsim,1]); %simulate external flood heights within bin (Uniform)
Esim4=Esim4.*(Esim4>=0); % make sure the difference is never below zero
% Cumulative flow volume 1 sim
CVol2_a=[]; CVol2_a=VBinEdges_Lo(IndMatCVol3(iCombCVol3,3));
CVol2_c=[]; CVol2_c=VBinEdges_Hi(IndMatCVol3(iCombCVol3,3));
pdCVol2=[]; pdCVol2=makedist('Uniform',CVol2_a,CVol2_c);
CVol2sim=[]; CVol2sim=random(pdCVol2,[Nsim,1]); %simulate external flood heights within bin (Uniform)
CVol2sim=CVol2sim.*(CVol2sim>=0); % make sure the difference is never below zero
CVol2sim(CVol2sim>=Vroom(:,1))=Vroom(:,1); % make sure the difference is never below zero
%fgsim installed or missing
p_fg = [0.97 0.03]; % prob of fg installed, missing
% fg state sim of installed or not
pd_fg = makedist('Binomial',1, p_fg(IndMatCVol3(iCombCVol3,2)));
fgsim = random(pd_fg,[Nsim,1]);
% Door state sim through area
Asim_door = Esim4*door_W;
Asim_door(Asim_door<0)=0; % make sure the area is postive
Asim_door(Asim_door>A_door)=A_door; %make sure area is never bigger than the possible area of door
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Asim_door(fgsim>=1 & Esim4<=n_fg)=0; %fg installed, Esim below n_fg then no A_door flow area available
Asim_door(fgsim>=1 & Esim4>=n_fg)=(Asim_door./A_fg); %fg installed, Esim above n_fg then A_door/A_fg flow area available
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Volumetric flow rate 2 sim calculation
Qsim_door=[]; Qsim_door=Cd.*Asim_door.*sqrt(2*g*(Esim4)); %ft^3/s
Qsim_door=Qsim_door.*(Qsim_door>=0); %Ensures positivity
Qsim_door(Esim4<=n_ps)=1E-20; %No flow when Esim is less than or equal to installation height
% Flow volume sim calculation
Vsim_door=[]; Vsim_door=Qsim_door.*Dsim; %ft^3
Vsim_door=Vsim_door.*(Vsim_door>=0); %ensure positivity
Vsim_door(Vsim_door>=Vroom(:,1))=Vroom(:,1); %Ensure Vsim is less than Vroom (3 Vroom configs)
Vsim_door(Esim4<=n_ps)=1E-20; %No flow volume when Esim is less than or equal to installation height
% Cumulative flow 1 sim calculation
CVol3sim= CVol2sim+Vsim_door;
CVol3sim=CVol3sim.*(CVol3sim>=0); %ensure positivity
CVol3sim(CVol3sim>=Vroom(:,1))=Vroom(:,1);
CVol3sim(CVol2sim<=0 & Vsim_door<=0)=0; % No cumulative flow 3 if CVol2 and Vsim_door have no flow
% Histogram
Hist_CVol3=[]; [Hist_CVol3,~] = histcounts(CVol3sim,VBinEdges);
Hist_CVol3=Hist_CVol3';
PMF_CVol3(:,iCombCVol3)=Hist_CVol3./sum(Hist_CVol3); % Bins it by the parents
end

Réponse acceptée

Voss
Voss le 6 Sep 2023
In this line, you have the entire array Asim_door (divided by A_fg) on the right side, trying to assign it to a subset on the left side. That's the problem.
Asim_door(fgsim>=1 & Esim4>=n_fg)=(Asim_door./A_fg); %fg installed, Esim above n_fg then A_door/A_fg flow area available
You have to use the same indices on both sides.
So if A_fg is a scalar:
idx = fgsim>=1 & Esim4>=n_fg;
Asim_door(idx) = Asim_door(idx)./A_fg; %fg installed, Esim above n_fg then A_door/A_fg flow area available
Or if A_fg is an array the same size as Asim_door:
idx = fgsim>=1 & Esim4>=n_fg;
Asim_door(idx) = Asim_door(idx)./A_fg(idx); %fg installed, Esim above n_fg then A_door/A_fg flow area available
What's the difference between doing it this way and an if statement?
Doing it this way (using logical indexing) is more concise and likely to be faster than using an if statement. With an if, you'd need to loop over the elements, e.g., if A_fg, n_fg and fgsim are arrays the same size as Asim_door:
for ii = 1:numel(Esim4)
if fgsim(ii) >= 1 && Esim4(ii) >= n_fg(ii)
Asim_door(ii) = Asim_door(ii)./A_fg(ii);
end
end
and if any of them are scalars, remove the (ii) indexing for those (and you could likely simplify the logic, e.g., if fg_sim is a scalar, you do not need to perform the loop at all if fg_sim < 1).
Note that the logical indexing expression
idx = fgsim>=1 & Esim4>=n_fg;
works the same regardless of whether n_fg and/or fgsim are scalars because of how & works:
true & [false false true]
ans = 1×3 logical array
0 0 1
[true true true] & [false false true]
ans = 1×3 logical array
0 0 1
  1 commentaire
Joy Shen
Joy Shen le 7 Sep 2023
Thanks @Voss, this helped with my code. Are there rules of thumb for the order of these conditional statements? Here's my updated code. For each Volume and Area I've restricted them from 0 to the maximum area. I wasn't the tidiest with order, but I wasn't sure if it mattered that much. This is still giving me strange results so I figured I'd ask.
for iCombCVol3=1:size(IndMatCVol3) %Parent PS1 has 3 states for child node Vi
% EFH loc 4 sim
EFH4_a=[]; EFH4_a=ExtSurgeBinEdges_door_Lo(IndMatCVol3(iCombCVol3,4));
EFH4_c=[]; EFH4_c=ExtSurgeBinEdges_door_Hi(IndMatCVol3(iCombCVol3,4));
pdEFH4=[]; pdEFH4=makedist('Uniform',EFH4_a,EFH4_c);
Esim4=[]; Esim4=random(pdEFH4,[Nsim,1]); %simulate external flood heights within bin (Uniform)
Esim4=Esim4.*(Esim4>=0); % Ensure positivity
% Cumulative flow volume 1 sim
CVol2_a=[]; CVol2_a=VBinEdges_Lo(IndMatCVol3(iCombCVol3,3));
CVol2_c=[]; CVol2_c=VBinEdges_Hi(IndMatCVol3(iCombCVol3,3));
pdCVol2=[]; pdCVol2=makedist('Uniform',CVol2_a,CVol2_c);
CVol2sim=[]; CVol2sim=random(pdCVol2,[Nsim,1]); %simulate external flood heights within bin (Uniform)
CVol2sim=CVol2sim.*(CVol2sim>=0); % Ensure positivity
CVol2sim(CVol2sim>=Vroom(:,1))=Vroom(:,1); % Cap it at room height
%fgsim installed or missing
p_fg = [0.97 0.03]; % prob of fg installed, missing
% fg state sim of installed or not
pd_fg = makedist('Binomial',1, 0.97);%Probability of fgsim installed %p_fg(IndMatCVol3(iCombCVol3,2)));
fgsim = random(pd_fg,[Nsim,1]);
% Door state sim through flow area with fg installed
Mu_door_fg=[]; Mu_door_fg=Amean_door(IndMatCVol3(iCombCVol3,1))-Amean_fg(IndMatCVol3(iCombCVol3,1));
Sig_door_fg=[]; Sig_door_fg=0.2*Mu_door_fg;
pd_Asim_door_fg=[]; pd_Asim_door_fg = makedist('normal',Mu_door_fg,Sig_door_fg);
Asim_door_fg = []; Asim_door_fg=random(pd_Asim_door_fg,[Nsim,1]);
Asim_door_fg(Esim4<=n_fg)=0;
% Door state sim through flow area with fg missing
Mu_door=[]; Mu_door=Amean_door(IndMatCVol3(iCombCVol3,1));
Sig_door=[]; Sig_door=0.2*Mu_door;
pd_Asim_door=[]; pd_Asim_door = makedist('normal',Mu_door,Sig_door);
Asim_door = []; Asim_door=random(pd_Asim_door,[Nsim,1]);
Asim_door(fgsim==1)=Asim_door_fg(fgsim==1); %When fgsim is installed, replace values with Asim_door_fg
Asim_door(fgsim==1 & Esim4<=n_fg)=0; %fg installed, Esim below n_fg then no A_door flow area available
Asim_door=Asim_door.*(Asim_door>=0); %Ensures positivity
Asim_door(Asim_door>=A_door)=A_door; % Cap it at door area
% Volumetric flow rate 2 sim calculation
Qsim_door=Cd.*Asim_door.*sqrt(2*g*Esim4);
Qsim_door_fg=Cd.*Asim_door_fg.*sqrt(2*g*(Esim4-n_fg)); %ft^3/s
Qsim_door_fg(Esim4<n_fg)=0;
Qsim_door(fgsim==1)=Qsim_door_fg(fgsim==1); %When fgsim is installed, replace values with Qsim_door_fg
Qsim_door(fgsim==1 & Esim4<=n_fg)=0; % Fg installed, no flow when Esim is less than or equal to installation height
Qsim_door=Qsim_door.*(Qsim_door>=0); %Ensures positivity
% Flow volume sim calculation
Vsim_door=[]; Vsim_door=Qsim_door.*Dsim; %ft^3
Vsim_door=Vsim_door.*(Vsim_door>=0); %ensure positivity
Vsim_door(fgsim==1 & Esim4<=n_fg)=0; %No flow volume when Esim is less than or equal to installation height
Vsim_door(Vsim_door>=Vroom(:,1))=Vroom(:,1); %Ensure Vsim is less than Vroom (3 Vroom configs)
% Cumulative flow 1 sim calculation
CVol3sim= CVol2sim+Vsim_door;
CVol3sim=CVol3sim.*(CVol3sim>=0); %ensure positivity
CVol3sim(CVol2sim<=0 & Vsim_door<=0)=0; % No cumulative flow 3 if CVol2 and Vsim_door have no flow
CVol3sim(CVol3sim>=Vroom(:,1))=Vroom(:,1); % Caps at the room volume
% Histogram
Hist_CVol3=[]; [Hist_CVol3,~] = histcounts(CVol3sim,VBinEdges);
Hist_CVol3=Hist_CVol3';
PMF_CVol3(:,iCombCVol3)=Hist_CVol3./sum(Hist_CVol3); % Bins it by the parents
end

Connectez-vous pour commenter.

Plus de réponses (1)

Steven Lord
Steven Lord le 6 Sep 2023
Esim4=Esim4.*(Esim4>=0); % make sure the difference is never below zero
I likely would just call the max function on Esim4 instead.
Esim4 = max(Esim4, 0);
Some of your other conditional steps could probably be replaced by calls to min and/or max instead of logical indexing (potentially combined with element-wise multiplication.)

Produits


Version

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by