I have an if loop, which for the most part works correctly, but the first if loop part is supposed to provide my resulting matrix in zeroes as long as the loop is below a certain threshold (12,4 in my case) however, it does not do this at the moment.
I have tried to replace everything, and rewrite it. I am currently following a guide, so I do not have an extensive amount of knowledge on the subject. I have tried to manually calculate the matrix positions, which should result in zero, which it also amounted to.
T_A4 = 12.4
t_coA = 3
F_redA = 0.99
for i = 5:25
t_r = i;
I(i,1) = 10980*(i*60).^(-0.71);
for n = 1:60
t = n;
if n < T_A4
Q(t,i) = 0;
end
if T_A4 <= t < t_coA + T_A4
Q(t,i) = I(i,1)*F_redA*(t-T_A4)/t_coA;
end
if t_coA + T_A4 <= t < T_A4 + t_r
Q(t,i) = I(i,1)*F_redA;
end
if t_r + T_A4 <= t < T_A4 + t_coA + t_r
Q(t,i) = I(i,1)*F_redA*(1-(t-T_A4-t_r)/t_coA);
end
if t >= T_A4 + t_coA + t_r
Q(t,i) = 0;
end
end
end
Expected result should be a Q matrix where Q(1:12,:) = 0, however from Q(1:12,5:25) these all results in values that is not 0.
An example is Q(1,5) should result in 0, as n=1 is < 12.4. However my resulting Q(1,5) = 1225.1 :(
Related
Suppose I have a function f(x) = cos(x). I want to evaluate f(x) in a form of g(x) = 1/2*f(0) + sum(1/4*f(a+h*i)) (for i is odd) + sum(3/4*f(a+h*i)) (for i is even except 0 and 10) + 1/2*f(b)
I write the code below, but it did not give the sum of (1/4*f(a+h*i)(for i is odd) and the sum of 3/4*f(a+h*i)(for i is even except 0 and 10).
a=0
h=0.1571
n=10
b=1.5708
for i = 1: n
simp_int2 = 0;
simp_int3 = 0;
simp_int1 = 1/2*f(0)
if i < n
if rem(i,2)~=0
simp_int2 = simp_int2 + 1/4*f(a+h*i)
end
if rem(i,2)==0
simp_int3 = simp_int3 + 3/4*f(a+h*i)
end
end
simp_int4 = 1/2*f(b)
end
simp_int = simp_int1 + simp_int2 + simp_int3 + simp_int4
I also tried cumsum and symsum. Both not working the way I intended. Thanks for any help!
You are resetting the accumulation variables at every iteration. Move the simp_* initializations to outside of the for loop.
Specifically:
a=0
h=0.1571
n=10
b=1.5708
% Change
simp_int1 = 1/2*f(0);
simp_int2 = 0;
simp_int3 = 0;
simp_int4 = 1/2*f(b);
for i = 1: n
if i < n
if rem(i,2)~=0
simp_int2 = simp_int2 + 1/4*f(a+h*i)
end
if rem(i,2)==0
simp_int3 = simp_int3 + 3/4*f(a+h*i)
end
end
end
simp_int = simp_int1 + simp_int2 + simp_int3 + simp_int4;
Since your function will return vector output for vector input you can do this without a for loop:
a=0
h=0.1571
n=10
b=1.5708
simp_int = 1/2*f(0) + sum(1/4*f(a + h*[1:2:n])) + sum(3/4*f(a+h*[2:2:n-1])) + 1/2*f(b)
Following up on a previous question, I have code that I think should limit the number of randomly generated points in each quadrant of the total tile; however, it is not working.
n = 4;
used = [];
k = 0;
a1_count = 0;
a2_count = 0;
a3_count = 0;
a4_count = 0;
min = 1;
max = 1;
while k<n
x = rand*2;
y = rand*2;
notvalid = 0;
if (0 <= x) && (x <= 1) && (0 <= y) && (y <= 1)
a1_count = a1_count + 1;
end
if (1 < x) && (x <= 2) && (0 <= y) && (y <= 1)
a2_count = a2_count + 1;
end
if (0 <= x) && (x <= 1) && (1 < y) && (y <= 2)
a3_count = a3_count + 1;
end
if (1 < x) && (x <= 2) && (1 < y) && (y <= 2)
a4_count = a4_count + 1;
end
%%%
if (min <= a1_count) && (a1_count <= max) && (min <= a2_count) && (a2_count <= max)...
&& (min <= a3_count) && (a3_count <= max) && (min <= a4_count) && (a4_count <= max)
notvalid=1;
end
if notvalid
continue
end
used(end+1,:) = [x;y];
k = k+1;
end
I wish to generate 4 random points, and have one in each quadrant of the total area. To do this, I have a maximum and minimum number of points in each quadrant (in this case 1), and an if statement to check that the count for each tile falls within the min and max. If it doesn't, then notvalid = 0 and the loop should begin again. This function doesn't seem to work however, as the loop finishes with 4 points total and is completely random (all the counts should = 1).
Can anyone spot where I'm going wrong?
I may be missing something, but the easiest approach would probably be something like
Select N random numbers within the x/y range of the first grid cell
Repeat for all grid cells
Here is some basic code that should create N random x/y points per grid cell
% Define the grid (for demonstration purposes)
dx = 1; dy = 1;
xrange = 0:dx:2;
yrange = 0:dy:2;
% Number of points per cell
N = 1;
[lowerx, lowery] = meshgrid(xrange(1:end-1), yrange(1:end-1));
% Store all those random numbers in a cell
data = cell(size(lowerx));
for k = 1:numel(lowerx);
% Generate 4 random points within the x/y range
xcoord = (rand(N, 1) * dx) + lowerx(k);
ycoord = (rand(N, 1) * dy) + lowery(k);
data{k} = [xcoord, ycoord];
end
disp(data)
data =
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
EDIT
To address your question directly using the code that you have provided, the logic in the code in your question is a little wonky. I have rewritten your while loop to be a little clearer so we can talk through it.
while k < n
x = rand * 2;
y = rand * 2;
if y >= 0 && y < 1
if x >= 0 && x < 1
a1_count = a1_count + 1;
else
a2_count = a2_count + 1;
end
else
if x >= 0 && x < 1
a3_count = a3_count + 1;
else
a4_count = a4_count + 1;
end
end
counts = [a1_count, a2_count, a3_count, a4_count];
notValid = all(counts >= minimum) && all(counts <= maximum);
if notValid
continue;
end
used(end+1,:) = [x;y];
k = k+1;
end
So the biggest thing is your notValid check. If you actually look at what you're checking (that all your *_count variables are within the pre-specified limits), I believe that if all of those conditions are true, then the current point is valid; however you state just the opposite.
Then you basically say, that if the current x y is valid, then add it to the used list. Well this logic is fine except that you define validity backwards as I stated before.
Ok so that aside, let's look at when you think that a point is not valid. Well, then you (correctly) go to the next iteration, but you never decrement the *_count variable. So say you had 1 point in quadrant 1 already and the second iteration through the loop it's in quadrant 1 again. Well you'd add 1 to a1_count and then see that it isn't valid (a1_count exceeds max) and go to the next loop, but a1_count stays at 2 despite really only having 1 because you just rejected it.
Now, all of that aside. Let's consider the first time through your loop and look at your validity check. Since you only add one point. Your validity check can never pass (if implemented correctly) because all *_count variables except the one that was just incremented will be less than the min.
So I think what happened is you probably did the validity check correctly at first, ended up with an infite while loop, and then negated that check, didn't get an infinite loop, but as a result got an incorrect solution.
The solution that you are getting currently, is literally the first 4 times through the while loop due to the incorrect logic.
If you really like your current approach, we can clean up the code to be correct.
n = 4;
used = zeros(0,2);
minimum = 1;
maximum = 1;
counts = [0 0 0 0];
while true
x = rand * 2;
y = rand * 2;
if y >= 0 && y < 1
if x >= 0 && x < 1
quadrant = 1;
else
quadrant = 2;
end
else
if x >= 0 && x < 1
quadrant = 3;
else
quadrant = 4;
end
end
% Check to see if we can even add this point
if counts(quadrant) + 1 > maximum
continue;
end
counts(quadrant) = counts(quadrant) + 1;
used = cat(1, used, [x, y]);
isComplete = all(counts >= minimum & counts <= maximum) && ...
size(used, 1) == n;
if isComplete
break
end
end
I'm trying to implement an inversion counter in MATLAB using MergeSort, but for some reason, some of the answers are way off. For example, the number of inversions in [3, 4, 8, 1] is 3, but I'm getting 2. However, the array is being sorted correctly, so I think that the way that I'm counting the split inversions is the problem.
Here's my code:
function [count, sorted] = mergesort(A)
% count is the number of inversions; sorted is the sorted array.
n = length(A);
if n == 1
count = 0;
sorted = A;
else
m = ceil(n/2);
[count1, sorted1] = mergesort(A(1:m));
[count2, sorted2] = mergesort(A(m+1:n));
[crosscount, sorted] = merge(sorted1, sorted2);
count = count1 + count2 + crosscount;
end
end
function [crosscount, z] = merge(x, y)
n = length(x); m = length(y); z = zeros(1, n+m);
ix = 1;
iy = 1;
crosscount = 0;
for iz = 1:(n+m);
if ix > n
z(iz) = y(iy);
iy = iy + 1;
elseif iy > m
z(iz) = x(ix);
ix = ix + 1;
crosscount = crosscount + (n + 1 - ix); %this might be wrong
elseif x(ix) <= y(iy)
z(iz) = x(ix);
ix = ix + 1;
elseif x(ix) > y(iy)
z(iz) = y(iy);
iy = iy + 1;
crosscount = crosscount + 1; %im pretty sure this is right
end
end
end
Alright, so a friend helped me figure it out. My intuition was correct, but I needed help from an actual programmer to understand where I went wrong:
elseif iy > m
z(iz) = x(ix);
ix = ix + 1;
crosscount = crosscount + (n + 1 - ix); **%this might be wrong - this is actually wrong, since you don't want to count if you're traversing beyond the edge of the right array, and since the actual counting is happening in the last if case**
elseif x(ix) <= y(iy)
z(iz) = x(ix);
ix = ix + 1;
elseif x(ix) > y(iy)
z(iz) = y(iy);
iy = iy + 1;
crosscount = crosscount + **(n + 1 - ix)** **this is right because you're counting the remaining numbers in your left array that are also greater than y(iy) and just adding that to your count**
end
Posting the entirety of my code in the hope somebody can help me debug this crap. Really hoping to reach a conclusion soon because I've been toying with this for way too long.
I have here a function extract which is passed a grid of integers which represent letters (i.e A=1,Z=26) from my wordsearch function. Given a direction and a target word which is represented by a row vector of ints, it should iterate through the grid to find where the first letter exists and move in all directions from here for length of the word and extract the word e.g. if we are looking for [14, 5, 9, 2] and 14 is first positioned at (4,4) we should end up at (4,8).
The word is then compared in the search function and if it matches the target word, a line is drawn from first letter to the last on an image of the actual wordsearch.
I know my if and for loops are off in some places but I'm finding it difficult to correct my code so that it works. Help! One thing in particular I'm having difficulty with is controlling flow so that if after checking all directions from a square containing the first letter, the next instance of that letter is evaluated. Where would it be best to do this?
Code has lots of errors as it is and could do with a couple of pointers telling me where it needs altering or cleaning up.
%//A function to find a word in a grid.
function test = extract(grid, direction, target)
%//switch through different cases that allow us to move to any adjacent cell to the current
switch upper(direction)
case 1
rowdir = -1;
coldir = 0;
case 2
rowdir = -1;
coldir = 1;
case 3
rowdir = 0;
coldir = 1;
case 4
rowdir = 1;
coldir = 1;
case 5
rowdir = 1;
coldir = 0;
case 6
rowdir = 1;
coldir = -1;
case 7
rowdir = 0;
coldir = -1;
case 8
rowdir = -1;
coldir = -1;
end
[i, j] = size(grid);
len = length(target);
[row,column] = find(target(1)==grid); %//find the letter of the word we are looking for in grid
%//row and column of last letter having moved in a particular direction
rowN = row + (len-1) * rowdir;
colN = column + (len-1) * coldir;
%//trying to say here to only move in a particular direction if we don't go out of bounds.
%//not sure I've succeeded
if (rowN > 1) | (rowN < i) | (colN > 1) | (colN < j)
testword = []; %empty array created
for index = 1:len
index_1 = index-1;
%//on loop get the letter in adjacent cell for direction we have moved
word = grid(row + (index_1 * rowdir), column + (index_1 * coldir));
testword{index} = word; %//letters are appended to create word for which we compare.
%//get co-ords of start letter. change to pixel co-ordinates so we can evaluate on image
wordstart = [(row*30)-15, (column*30)-15 ];
wordend = [((row + (len-1 * rowdir))*30)-15, ((column + (len-1 * coldir))*30)-15];
end
else
word = '';
end
x1 = wordstart(1);
x2 = wordend(1);
y1 = wordstart(2);
y2 = wordend(2);
test = [ word , [x1,x2] , [y1,y2]]; %//only way I could think of to get all of these as outputs
end
%//test is the image we want to evaluate on
%//words is the list of words
function trial1 = wordsearch(test, words)
imagesc(test);
colormap(gray);
hold on;
grid = %//grid is a 15x15 matrix
[row, column] = size(grid);
for iword = 1 : length(words)
target = char(words(iword)) - 'a' + 1;
for i = 1:row
for j = 1:column
for direction_num = 1:8 %//for each direction
direction = directions(direction_num, :);
testword = extract(grid,direction,target);
if testword(1)==target %//if word we have extracted equals the target word
%//draw_line function takes x co-ordinates and y co-ordinates and plots line.
draw_line(testword(2),testword(3),testword(4),testword(5));
end
end
end
end
end
hold off;
end
#Dan
My extract function now looks like:
[i, j] = size(grid);
len = length(target);
[row,column] = find(target(1)==grid);
for ii = 1:length(row)
start_row = row(ii);
start_column = column(ii);
rowN = start_row + len-1 * rowdir;
colN = start_column + len-1 * coldir;
if (rowN > 1) || (rowN < i) || (colN > 1) || (colN < j)
testword = [];
for index = 1:len
index_1 = index-1;
word = grid(start_row + (index_1 * rowdir), start_column + (index_1 * coldir));
testword{index} = word;
wordstart = [(start_row*30)-15, (start_column*30)-15 ];
wordend = [((start_row + (len-1 * rowdir))*30)-15, ((start_column + (len-1 * coldir))*30)-15];
end
else
end
end
What would I put as an else statement to check the word if previous in that particular direction takes you out of bounds?
for iword = 1 : length(words)
target = char(words(iword)) - 'a' + 1;
for i = 1:row
for j = 1:column
for direction_num = 1:8 %//for each direction
For every word, you are looping through every element in the grid (i.e. the i and j loops) but you don't actually ever use these i or j values. So those two loops do nothing! This is because you seems to do all of that inside your extract function. So drop those two loops, they are wasting an inordinate amount of time.
Inside your extract function, you have a line [row,column] = find.... This will find ALL the possible starting points. So you actually need to loop through either of those somewhere. So instead of your if (rowN > 1) | (rowN < i) | (colN > 1) | (colN < j) I would suggest something more like:
for ii = 1:length(row)
start_row = row(ii);
start_column = column(ii);
%// And now re-use your code, but swap out all your row for start_row and your column for start_column
.
.
.
end
That is the loop that will go through each of the possible starting letters.
I have the following error in MATLAB:
??? Subscript indices must either be real positive integers or
logicals.
Error in ==> Lloyd_Max at 74 D(w_count) = mean((x -
centers(xq)).^2);
This is my code :
function [ xq,centers,D ] = Lloyd_Max( x,N,min_value,max_value )
%LLOYD_MAX Summary of this function goes here
% Detailed explanation goes here
x = x';
temp = (max_value - min_value)/2^N;
count=1;
for j=0:temp:((max_value - min_value)-temp),
centers(count) = (j + j + temp )/2;
count = count + 1;
end
for i=1:length(centers),
k(i) = centers(i);
end
w_count = 0;
while((w_count < 2) || (D(w_count) - D(w_count - 1) > 1e-6))
w_count = w_count + 1;
count1 = 2;
for i=2:(count-1),
T(i) = (k(i-1) + k(i))/2;
count1 = count1 +1 ;
end
T(1) = min_value;
T(count1) = max_value;
index = 1;
for j=2:count1,
tempc = 0;
tempk = 0;
for k=1:10000,
if(x(k) >= T(j-1) && x(k) < T(j))
tempk = tempk + x(k);
tempc = tempc + 1;
end
end
k(index) = tempk;
k_count(index) = tempc;
index = index + 1;
end
for i=1:length(k),
k(i) = k(i)/k_count(i);
end
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
for i=1:10000,
cnt = 1;
for l=2:count1,
if(xq(i) > T(l-1) && xq(i) <= T(l))
xq(i) = cnt;
end
cnt = cnt +1 ;
end
end
D(w_count) = mean((x - centers(xq)).^2);
end
end
and i call it and have these inputs :
M = 10000
t=(randn(M,1)+sqrt(-1)*randn(M,1))./sqrt(2);
A= abs(t).^2;
[xq,centers,D] = Lloyd_Max( A,2,0,4 );
I tried to comment the while and the D, Results :
I got the xq and the centers all normal, xq in the 1-4 range, centers 1-4 indexes and 0.5-3.5 range.
I dont know whats going wrong here...Please help me.
Thank in advance!
MYSTERY SOVLED!
Thank you all guys for your help!
I just putted out of the while the for loop :
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
and it worked like charm.... this loop was initilizing the array again. Sorry for that. Thank you again!
There is an assignment xq(i) = x(i) somewhere in the middle of your function, but you pass A as x from outside where you calculate A from t which is sampled by randn, so you can't promise xq is an integer.
I'm not sure exactly what you are aiming to do, but your vector xq does not contain integers, it contains doubles. If you want to use a vector of indices as you do with centers(xq), all elements of the vector need to be integers.
Upon a little inspection, it looks like xq are x values, you should find some way to map them to the integer of the closest cell to which they belong (i'm guessing 'centers' represents centers of cells?)