Matlab: "Matrix Exceeds Dimensions Error" in While Loop? - matlab

My tutor and I were solving problem simulating the war card game. The only variation in the rules is that two cards with same value are both discarded.
My tutor and I came up with a solution
deck1 = randi(13,1,26);
deck2 = randi(13,1,26);
winner1 = 0;
winner2 = 0;
n = 1;
while (length(deck1) ~= 0 || length(deck1) ~= 0)
n = length(deck1);
m = length(deck2);
if deck1(1) == deck2(1)
deck1(1) = [];
deck2(1) = [];
elseif deck1(1) < deck2(1)
winner2 = winner2 + 1;
deck2(m+1) = deck2(1);
deck1(1) = [];
deck2(1) = [];
else
deck1(27) = deck1(1);
deck1(n+1) = deck2(1);
deck1(1) = [];
deck2(1) = [];
winner1 = winner1 + 1;
end
end
if winner1 > winner2
k = 1;
elseif winner1 == winner2
k = 0;
else k = 2;
end
disp(k)
The loop works for k=2 and k=0 but not for k=1. It return the following
Index exceeds matrix dimensions.
Error in TutorVersionWarCardGame (line 16)
if deck1(1) == deck2(1)
How should I edit the loop?

You compare deck1 2 times in the while loop as below
while (length(deck1) ~= 0 || length(deck1) ~= 0)
I think it should be
while (length(deck1) ~= 0 || length(deck2) ~= 0)
Edit:
I added try catch to check the if conditions inside the while loop. I found matrix keep decrease until its size reaches to 0, therefore, I replace the || with && while (length(deck1) ~= 0 && length(deck2) ~= 0) but the result now always k=2.

This works for me:
deck1 = randi(13,1,26);
deck2 = randi(13,1,26);
winner1 = 0;
winner2 = 0;
n = 1;
while (~isempty(deck1) && ~isempty(deck2))
n = length(deck1);
m = length(deck2);
if deck1(1) == deck2(1)
deck1(1) = [];
deck2(1) = [];
elseif deck1(1) < deck2(1)
winner2 = winner2 + 1;
deck2(m+1) = deck2(1);
deck1(1) = [];
deck2(1) = [];
else
deck1(27) = deck1(1);
deck1(n+1) = deck2(1);
deck1(1) = [];
deck2(1) = [];
winner1 = winner1 + 1;
end
end
if winner1 > winner2
k = 1;
elseif winner1 == winner2
k = 0;
else
k = 2;
end
disp(k);

Related

How to create object within function MatLab without creating a new file

I am working on a project with the following specs:
https://drive.google.com/file/d/14xaCK-1Mpd8FXM-19pfFC1UTk2V9oXkQ/view?usp=sharing
My code is attached below.
How do I get my final output as a data object and info object like they are asking, without creating a new class file? The format required is in the picture below.
Final format required:
function [data,info] = OneNormLPxxx(A,b)
%L1 norm minimization for a given A and b.
% Detailed explanation goes here
count = 0;
b_vect = b;
[m,n] = size(A);
max_count = 3*nchoosek(m,n);
set_B = 1:n;
M = inv(A(set_B, :));
is_opt = 0;
while (is_opt == 0)
if (det(A(set_B,:)) == 0)
info = untitled4;
info.run = "Failure";
info.msg = "Degeneracy Problem";
data = untitled3;
return
end
if (max_count <= count)
info = untitled4;
info.run = "Failure";
info.msg = "Arithmetic Problem";
data = untitled3;
return
end
set_B_Comp = setdiff(1:m,set_B);
x_temp = M*b_vect(set_B);
h = A*x_temp - b_vect;
h(set_B_Comp) = A(set_B_Comp,:)*x_temp - b_vect(set_B_Comp);
y_vect = zeros(m, 1);
y_vect(set_B_Comp) = sign(h(set_B_Comp));
y_vect(set_B) = -(M')*((A(set_B_Comp,:)')*y_vect(set_B_Comp));
abs_y_B = abs(y_vect(set_B));
if all(abs_y_B <= 1)
is_opt = 1;
x_opt = x_temp;
opt_val = sum(abs(A*x_opt - b_vect));
data = untitled3;
data.obj = opt_val;
data.x = x_opt;
data.loop = count;
info = untitled4;
info.run = "Success";
return
% return B and x
else
all_index_y_vect_more_than_1 = find(abs(y_vect(set_B)) > 1);
s = all_index_y_vect_more_than_1(1);
y_s = y_vect(s);
t_vect = zeros(m, 1);
t_vect(set_B_Comp) = -(sign(y_s))*(y_vect(set_B_Comp)).*(A(set_B_Comp,:)*M(:,s));
cur_min = abs(h(set_B_Comp(1)))/t_vect(set_B_Comp(1)) + 1;
cur_r = set_B_Comp(1);
for j = set_B_Comp
h_j = h(j);
t_j = t_vect(j);
temp1 = abs(h_j)/t_j;
if (temp1 < cur_min) && (temp1 > 0) && (t_j > 0)
cur_min = temp1;
cur_r = j;
end
end
r = cur_r;
j_s = set_B(s);
set_B_new = setdiff(union(set_B, r), j_s);
set_B = set_B_new;
set_B_Comp = setdiff(1:m,set_B);
theta = (A(r,:)*M)';
M(:,s) = (1/theta(s))*M(:,s);
for j = 1:n
if (j ~= s)
M(:,j) = M(:,j) - theta(j)*M(:,s);
end
end
end
count = count + 1;
end
end
Rather than using
info = untitled4;
Use
info = struct();
This will create a MATLAB structure for storing your data.

Simulate a custom function in Matlab

I'd like to simulate the following function:
l(t) = mu + Σ (1 + (t-t_i)/alpha)^(beta)
I wrote the function as follow:
function[l] = custom(m,t,H,par)
k = length(H);
n = length(t);
l = par.mu(m)*ones(n,1);
for i = 1:n
for j = 1:k
h = H{j};
h = h(h < t(i));
if ~isempty(h)
d = t(i) - h;
l(i) = l(i) + sum((1+ (d/par.alpha(m,j)))^ par.beta(m,j));
end
end
end
Now, how can I simulate this function for t=1000, par.mu= 0.5, par.alpha = 0.1, par.beta = 0.3?
I have the following code for simulation of this function but it's not efficient...How can I make it better?
function[h] = simcustom(t,par)
h = -log(rand)/par.mu;
if h < t
do5 = 1;
i = 0;
j = 0;
k = 0;
n = 1;
while true
if do5;
k = k + 1;
Lstar(k) = custom(1,h(n),{h},par); %#ok
end
j = j + 1;
U(j) = rand; %#ok
i = i + 1;
u(i) = -log(U(j))/Lstar(k); %#ok
if i == 1
Tstar(i) = u(i); %#ok
else
Tstar(i) = Tstar(i-1) + u(i);
end
if Tstar(i) > t
h = {h};
break
end
j = j + 1;
U(j) = rand;
if U(j) <= custom(1,Tstar(i),{h},par)/Lstar(k)
n = n + 1;
h = [h Tstar(i)];
do5 = true;
else
k = k + 1;
Lstar(k) = custom(1,Tstar(i),{h},par);
do5 = false;
end
end
else
h = {[]};
end
And here is the application:
par2.mu = 0.5;
par2.alpha = 0.1;
par2.beta = 0.3;
t = 1000;
h2 = simcustom(t,par2);

Matlab coder "Error indenting generated C code"

I am Trying to convert a MATLAB code to C++ using MATLAB coder but this error apears:
Error indenting generated C code
The error points to the name of the function itself and has no more explanations in it. can someone tell me what is this error?
here is the function i want to conver:
function [Report_Clustered,ClusterCounter_new]=InitClusterGenerator_test(Report_In,~,FreqEpsilon,DegreeEpsilon,~,ClusterCounter_old, BlockCount, Report_old)
Report_M = zeros(size(Report_In,1),size(Report_In,2),4);
for i=1:size(Report_In,1)
for j=1:size(Report_In,2)
Report_M(i,j,1)=Report_In(i,j,1);
Report_M(i,j,2)=Report_In(i,j,2);
Report_M(i,j,3)=0; % Cluster number that the point belongs to.
Report_M(i,j,4)=0;
Report_In{i,j}
end
end
ClusterCounter = 0;
for i=1:size(Report_M,1)
for j=1:size(Report_M,2)
if (Report_M(i,j,3) == 0)
ClusterCounter = ClusterCounter + 1;
Report_M(i,j,3) = ClusterCounter;
for ii=1:size(Report_M,1)
for jj=1:size(Report_M,2)
if (Report_M(ii,jj,3) == 0)
if (abs(Report_M(i,j,1)-Report_M(ii,jj,1))<FreqEpsilon &&...
(abs(Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon ||...
abs(-360 + Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon ||...
abs(360 + Report_M(i,j,2)-Report_M(ii,jj,2)) <DegreeEpsilon))
Report_M(ii,jj,3) = ClusterCounter;
end
end
end
end
end
end
end
if (BlockCount> 20 && ClusterCounter<4)
warning = 1;
end
ClusterCounter_new = ClusterCounter;
%clear Report_new;
flag = 0;
Report_new = zeros(ClusterCounter,size (Report_M, 2),4);
index = zeros(1, ClusterCounter_new);
for i = 1: size (Report_M, 1)
for j = 1: size (Report_M, 2)
for k = 1: ClusterCounter_new
if (Report_M(i,j,3) == k)
index(1,k) = index(1,k) + 1;
Report_new(k,index(1,k), 1:3) = Report_M(i,j,1:3);
flag = flag + 1;
end
end
end
end
for j = 1: size (Report_new, 2)
for i = 1: size (Report_new, 1)
if (Report_new(i,j,1) == 0)
Report_new(i,j,1:3) = Report_new(i,1,1:3);
end
end
end
%Report_new = Report;
MedoidF_old = zeros(1, size(Report_old,1));
MedoidA_old = zeros(1, size(Report_old,1));
for i=1:size(Report_old,1)
SumF = 0;
SumA = 0;
MinAngle = 361;
MaxAngle = -1;
for j=1:size(Report_old,2)
SumF = SumF + Report_old(i,j,1);
SumA = SumA + Report_old(i,j,2);
if Report_old(i,j,2) > MaxAngle
MaxAngle = Report_old(i,j,2);
elseif Report_old(i,j,2) < MinAngle
MinAngle = Report_old(i,j,2);
end
end
MedoidF_old(1, i) = SumF/size(Report_old,2);
if (MaxAngle - MinAngle) > 350
MedoidA_old(1, i) = 0;
else
MedoidA_old(1, i) = SumA/size(Report_old,2);
end
end
MedoidF_new = zeros(1, size(Report_new,1));
MedoidA_new = zeros(1, size(Report_new,1));
for i=1:size(Report_new,1)
SumF = 0;
SumA = 0;
MinAngle = 361;
MaxAngle = -1;
for j=1:size(Report_new,2)
SumF = SumF + Report_new(i,j,1);
SumA = SumA + Report_new(i,j,2);
if Report_new(i,j,2) > MaxAngle
MaxAngle = Report_new(i,j,2);
elseif Report_new(i,j,2) < MinAngle
MinAngle = Report_new(i,j,2);
end
end
MedoidF_new(1, i) = SumF/size(Report_new,2);
if (MaxAngle - MinAngle) > 350
MedoidA_new(1, i) = 0;
else
MedoidA_new(1, i) = SumA/size(Report_new,2);
end
end
TempCluster = zeros(1, size(Report_new, 1));
CurrentCluster = ClusterCounter_old;
for i = 1: 1: size(Report_new,1)
for j = 1: 1: size(Report_old,1)
if (abs(MedoidF_old(1,j)-MedoidF_new(1,i))<FreqEpsilon &&...
(abs(MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||...
abs(360 + MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||...
abs(-360 + MedoidA_old(1,j)-MedoidA_new(1,i))<DegreeEpsilon)) %%if the new cluster is the rest of an old cluster use the old one's index for it
TempCluster(1,i) = Report_old(j,1,3);
end
end
%%this part is for seperating the clusters which where in the collision state in the past time
if (TempCluster(1,i)>0) %%if the new cluster is one of the old ones the index should be set
for j = 1:1:size(Report_new, 2)
Report_new(i,j,3) = TempCluster(1,i);
Report_new(i,j,4) = 1;% Alive
end
else %%first search if the new cluster is a part of a newly found cluster found before this one
for j = 1: 1: i-1
if (abs(MedoidF_new(1,j)-MedoidF_new(1,i))<FreqEpsilon &&...
(abs(MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||...
abs(360 + MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon ||...
abs(-360 + MedoidA_new(1,j)-MedoidA_new(1,i))<DegreeEpsilon)) %%if the new cluster is the rest of an old cluster use the old one's index for it
TempCluster(1,i) = Report_new(j,1,3);
end
end
end
if (TempCluster(1,i)>0) %%if the new cluster is one of the old ones the index should be set
for j = 1:1:size(Report_new, 2)
Report_new(i,j,3) = TempCluster(1,i);
Report_new(i,j,4) = 1;% Alive
end
else %%new cluster is just began so it needs a new index
CurrentCluster = CurrentCluster + 1;
ClusterCounter_new = CurrentCluster;
TempCluster(1,i) = CurrentCluster;
for j = 1:1:size(Report_new, 2)
Report_new(i,j,3) = TempCluster(1,i);
Report_new(i,j,4) = 1; % Alive
end
end
end
NewClusters = zeros(1, size (Report_new, 1));
for i = 1: size(Report_new, 1)
NewClusters (1,i) = Report_new(i,1,3);
end
OldClusters = zeros(1, size (Report_old, 1));
OldClustersLine = zeros(1, size (Report_old, 1));
for i = 1: size(Report_old, 1)
OldClusters (1,i) = Report_old(i,1,3);
OldClustersLine (1, i) = i;
end
NumberOfDead = 0;
%clear AddDead;
AddDead = zeros (16,size(Report_new, 2),4);
if (BlockCount>10)
for i = 1: size (OldClusters, 2)
IsDead = 1;
for j = 1: size (NewClusters, 2)
if OldClusters(1, i) == NewClusters(1,j)
IsDead = 0;
end
end
if (IsDead == 1)
NumberOfDead = NumberOfDead + 1;
%clear TempLine;
TempLine = zeros(1, size(Report_old,2), 4);
TempLine(1,:,1:3) = Report_old(OldClustersLine(1, i),:,1:3);
for k= 1: size(TempLine, 2)
TempLine(1,k,4) = 0; % Dead
end
TempSize = size(TempLine, 2);
Thresh = size(Report_new, 2);
if (TempSize >= Thresh)
AddDead (NumberOfDead, 1:Thresh, 1:4) = TempLine(1,1:Thresh, 1:4);
else
for l = 1: Thresh-TempSize
TempLine(1, TempSize+l, 1:4) = TempLine(1, TempSize, 1:4);
end
AddDead (NumberOfDead, 1:Thresh, 1:4) = TempLine(1,1:Thresh, 1:4);
end
end
end
xR = size (Report_new,1);
if (NumberOfDead == 0)
Report_Clustered = zeros (size(Report_new,1),size(Report_new,2),size(Report_new,3));
else
Report_Clustered = zeros (size(Report_new,1) + NumberOfDead,size(Report_new,2),size(Report_new,3));
end
Report_Clustered (1:size(Report_new,1), :, :) = Report_new(:,:,:);
for i = 1: NumberOfDead
Report_Clustered(xR + i, :) = AddDead(i, :);
end
end
and I'm using matlab 2012a
Tnx.
From what you've said in the comments, it appears that you simply need to call
clear functions
from the command line before recompiling the function to allow Matlab to overwrite the files. See this Matlab forum or the documentation for clear for more detail.

Filter points using hist in matlab

I have a vector. I want to remove outliers. I got bin and no of values in that bin. I want to remove all points based on the number of elements in each bin.
Data:
d1 =[
360.471912914169
505.084636471948
514.39429429184
505.285068055647
536.321181755858
503.025854206322
534.304229816684
393.387035881967
396.497969729985
520.592172434431
421.284713703215
420.401106087984
537.05330275495
396.715779872694
514.39429429184
404.442344469518
476.846474245118
599.020867750031
429.163139144079
514.941744277933
445.426761656729
531.013596812737
374.977332648255
364.660115724218
538.306752697753
519.042387479096
1412.54699036882
405.571202133485
516.606049132218
2289.49623498271
378.228766753667
504.730621222846
358.715764917016
462.339366699398
512.429858614816
394.778786157514
366
498.760463549388
366.552861126468
355.37022947906
358.308526273099
376.745272034036
366.934599077274
536.0901883079
483.01740134285
508.975480745389
365.629593988233
536.368800360349
557.024236456548
366.776498701866
501.007025898839
330.686029339009
508.395475983019
429.563732174866
2224.68806802212
534.655786464525
518.711297351426
534.304229816684
514.941744277933
420.32368479542
367.129404978681
525.626188464768
388.329756778952
1251.30895065927
525.626188464768
412.313764019587
513.697381733643
506.675438520558
1517.71183364959
550.276294237722
543.359917550053
500.639590923451
395.129864728041];
Histogram computation:
[nelements,centers] = hist(d1);
nelements=55 13 0 0 1 1 1 0 0 2
I want to remove all points apearing less than 5 (in nelements). It means only first 2 elements in nelements( 55, 13 ) remains.
Is there any function in matlab.
You can do it along these lines:
threshold = 5;
bin_halfwidth = (centers(2)-centers(1))/2;
keep = ~any(abs(bsxfun(#minus, d1, centers(nelements<threshold))) < bin_halfwidth , 2);
d1_keep = d1(keep);
Does this do what you want?
binwidth = centers(2)-centers(1);
centersOfRemainingBins = centers(nelements>5);
remainingvals = false(length(d1),1);
for ii = 1:length(centersOfRemainingBins )
remainingvals = remainingvals | (d1>centersOfRemainingBins (ii)-binwidth/2 & d1<centersOfRemainingBins (ii)+binwidth/2);
end
d_out = d1(remainingvals);
I don't know Matlab function for this problem, but I think, that function with follow code is what are you looking for:
sizeData = size(data);
function filter_hist = filter_hist(data, binCountRemove)
if or(max(sizeData) == 0, binCountRemove < 1)
disp('Error input!');
filter_hist = [];
return;
end
[n, c] = hist(data);
sizeN = size(n);
intervalSize = c(2) - c(1);
if sizeData(1) > sizeData(2)
temp = transpose(data);
else
temp = data;
end
for i = 1:1:max(sizeN)
if n(i) < binCountRemove
a = c(i) - intervalSize / 2;
b = c(i) + intervalSize / 2;
sizeTemp = size(temp);
removeInds = [];
k = 0;
for j = 1:1:max(sizeTemp)
if and(temp(j) > a, less_equal(temp(j), b) == 1)
k = k + 1;
removeInds(k) = j;
end
end
temp(removeInds) = [];
end
end
filter_hist = transpose(temp);
%Determines when 'a' less or equal to 'b' by accuracy
function less_equal = less_equal(a, b)
delta = 10^-6; %Accuracy
if a < b
less_equal = 1;
return;
end
if abs(b - a) < delta
less_equal = 1;
return;
end
less_equal = 0;
You can do something like this
nelements=nelements((nelements >5))

incapsulation of a code inmatlab

my code is
pathname=uigetdir;
filename=uigetfile('*.txt','choose a file name.');
data=importdata(filename);
element= (data.data(:,10));
in_array=element; pattern= [1 3];
locations = cell(1, numel(pattern));
for p = 1:(numel(pattern))
locations{p} = find(in_array == pattern(p));
end
idx2 = [];
for p = 1:numel(locations{1})
start_value = locations{1}(p);
for q = 2:numel(locations)
found = true;
if (~any((start_value + q - 1) == locations{q}))
found = false;
break;
end
end
if (found)
idx2(end + 1) = locations{1}(p);
end
end
[m2,n2]=size(idx2)
res_name= {'one' 'two'};
res=[n n2];
In this code I finding a pattern in one of the column of my data file and counting how many times it's repeated.
I have like 200 files that I want to do the same with them but unfotunatlly I'm stuck.
this is what I have added so far
pathname=uigetdir;
files=dir('*.txt');
for k=1:length(files)
filename=files(k).name;
data(k)=importdata(files(k).name);
element{k}=data(1,k).data(:,20);
in_array=element;pattern= [1 3];
locations = cell(1, numel(pattern));
for p = 1:(numel(pattern))
locations{p} = find(in_array{k}== pattern(p));
end
idx2{k} = [];
how can I continue this code..??
OK, first define this function:
function [inds, indsy] = findPattern(M, pat, dim)
indices = [];
if nargin == 2
dim = 1;
if size(M,1) == 1
dim = 2; end
end
if dim == 1
if numel(pat) > size(M,1)
return; end
for ii = 1:size(M,2)
inds = findPatternCol(M(:,ii), pat);
indices = [indices; repmat(ii,numel(inds),1) inds]%#ok
end
elseif dim == 2
if numel(pat) > size(M,2)
return; end
for ii = 1:size(M,1)
inds = findPatternCol(M(ii,:).', pat);
indices = [indices; inds repmat(ii,numel(inds),1)]%#ok
end
else
end
inds = indices;
if nargout > 1
inds = indices(:,1);
indsy = indices(:,2);
end
end
function indices = findPatternCol(col, pat)
inds = find(col == pat(1));
ii = 1;
prevInds = [];
while ~isempty(inds) && ii<numel(pat) && numel(prevInds)~=numel(inds)
prevInds = inds;
inds = inds(inds+ii<=numel(col) & col(inds+ii)==pat(ii+1));
ii = ii + 1;
end
indices = inds(:);
end
which is decent but probably not the most efficient. If performance becomes a problem, start here with optimizations.
Now loop through each file like so:
pathname = uigetdir;
files = dir('*.txt');
indices = cell(length(files), 1);
for k = 1:length(files)
filename = files(k).name;
data(k) = importdata(files(k).name);
array = data(1,k).data(:,20);
pattern = [1 3];
indices{k} = findPattern(array, pattern);
end
The number of occurrences of the pattern can be found like so:
counts = cellfun(#(x)size(x,1), indices);